2019/12/14

itextSharp繪製表單使用攻略(如何美化)

筆者從2011年開始接觸itextsharp這個從java轉到c#的套件,累積了一些心得與大家分享。

一、itextSharp 的物件概念很徹底,從文件本體的 doc 出發,最小單元的phrase(詞彙),到paragraph(段落),乃至於table,都是以組件的方式新增到doc之中。因為用法很靈活,初學者很常會搞不清楚而寫出冗長的程式碼。

例如畫出一個表格,語法大概像下面這樣,先指定有幾欄、帶入每欄寬度、表格的寬度,以及欄位的padding預設值。可以用預設值方式設定格子的留白(padding),看起來較專業。若是padding沒設,字會跟儲存格黏再一起,感覺就像是工程師畫的 XD

float[] tbPreReqColWidth = { 250f, 250f, 250f, 250f };


PdfPTable tbCredit = new PdfPTable(4);
tbCredit.SetWidths(tbPreReqColWidth);
tbCredit.WidthPercentage = 95; //寬度
tbCredit.DefaultCell.Padding = 7;

若是宣告好 paragraph,直接用addcell方法塞進表格而產生cell的,會自動套用 DefaultCell的屬性值,如:
tbCredit.AddCell(thisTeach2);
 
若是這是個需要獨立個別屬性的儲存格,就不受到tbCredit.DefaultCell底下屬性的影響,必須都自己來。
Paragraph BriefTitle = new Paragraph("一、教師姓名:" + query1.NAME_CH.Trim() + "\n", largeFontBold);
BriefTitle.Alignment = Element.ALIGN_LEFT;



PdfPCell cellTitle = new PdfPCell(BriefTitle);
cellTitle.Colspan = 4;
cellTitle.PaddingBottom = 7;
cellTitle.BackgroundColor = new BaseColor(System.Drawing.Color.LightGray);
tbCredit.AddCell(cellTitle);
二、itextsharp如果遇到一個段落內有不同語系的語言,按照比較正規的做法,應該是針對每段不同語系的字源內容產生phrase,然後塞到paragraph內。偏偏itextsharp要顯示文字,還要吃Server上的字體,否則可能會完全不能顯示,或只顯示某些內容。

有些字體是包含不同粗細的,在新增字體的後面會多個變數去取組合內的第幾套。
public static BaseFont bfChinese = BaseFont.CreateFont("c://windows/fonts/kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//正黑體
//public static BaseFont hei_ti = BaseFont.CreateFont("c://windows/fonts/msjh.ttc,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//public static BaseFont korean = BaseFont.CreateFont("c://windows/fonts/GULIM.TTC,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// public static BaseFont arial = BaseFont.CreateFont("c://windows/fonts/arial.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
 

以筆者遇過的系統而言,雖然程式與資料庫欄位都是使用萬國碼,因此理論上所有字元都可容納;但若填報單位使用的字元,使用頻率較低者,或者是非西歐語系的語文,標楷體、明體可能顯示不出來。 但是比較新問世的微軟黑體等等,則可以顯示。
另外也分享之前科普的心得,C#針對 unicode 裡特殊語言的定義叫做 named blocks,
幾個主流語言很幸運的有被界定出來。但如果是很罕見的就慘了,即使程式能把他識別出來,也要找得到能顯示的字型,才能讓它顯示在電子文件中。

大部分的西歐語言或羅馬拼音,都是字根,使用的編碼範圍不多,因此掉字的機會小一些。
中日韓文的每一個「方塊字」則是包含不同的字根,所以字若不在共同表意文字範圍內,套錯字型了則根本無法顯示那個字。word內可以顯示,是因為word會自動幫沒字型的字去湊數。若用較專門的繪圖軟體,比較看得出差別。



2019/11/23

在EF中執行SQL查詢 (Execute Raw SQL Queries in Entity Framework)

EF(Entity Framework)是微軟提供的佛心ORM工具,讓菜鳥開發人員得以在操作後端資料庫時,可以在Visual Studio中以物件的方式選擇資料庫內的表格與欄位,減少手動組合SQL指令發生的錯誤。但若資料庫因正規劃切割成數十個表格,或者主索引鍵規劃不良、有許多子查詢時,檢查EF組合出的SQL語法,其時間成本可能遠遠超過原來所預期。

遇到這種情形,筆者可能會選擇設計View、資料表函數或者預存程序,在EF內加入此物件。但要記得回傳的查詢結果必須要有Key值。

另一種情形是開發者無法(或沒有權限)在DB上新增物件。可能的方案是直接在EF下 SQL語法。從舊有的程式翻修時,會遇到有複雜join的情形,靠EF Mapping可能會有錯。這時候可以手動帶參數進去。

using (var ctx = new SchoolDBEntities())
{
    var student = ctx.Students
                    .SqlQuery("Select * from Students where StudentId=@id", new SqlParameter("@id", 1))
                    .FirstOrDefault();
}
但這樣的sql如果選取的欄位名稱與EF內的物件名稱衝突,還是會產生Exception。

2019/11/5

The English Patient


記得學生時代在電視上看過電影「英倫情人」(The English Patient)的電視廣告,當中艾莫西與嘉芙琳翩翩起舞的情景,令人至今難忘(現在是2019,23個年頭過去了),那段配樂尤其迷人。

後來買了得利影視的正版VCD,也買了蓋布瑞·雅德作曲的原版原聲帶,但很奇怪,就是找不到跟當初電影預告片段裡的那段配樂。

後來電影看得多了,猛然發現,那時候的很多電影,似乎廣告曲跟片子本身的配樂,根本不是同一首! 是後製趕工不及,還是甚麼原因,就不得而知了。


現在有YouTube 跟Google可查,拜讀國外網友留言之後,總算解開心中迷惑。

英倫情人的這段廣告配樂,來自Randall Meyers(1955-) 為1993年挪威電影 Telegrafisten (電報員)創作的 Love Theme Rolandsen and Elisa 。電報員這部片由挪威作家 Knut Hamsun( 克努特·漢森)的作品 Dreamers (Sværmere) 改編而來,雖然入圍過奧斯卡最佳外語片,但鎩羽而歸。
以世俗的角度來看,影響力遠不如後來的英倫情人。

英倫情人配樂作曲者蓋布瑞·雅德所做的曲子,融合了匈牙利民謠與北非的意象,還有巴哈的郭爾堡變奏曲,與劇情緊密鑲嵌,但用現在的話來說,劇透可能太強烈了些。發行商Miramax不知為何,改選一首中規中矩代打的主題曲。這首代打跟英倫情人裡第三首配樂的前幾小節很相似,後面則屬於中規中矩,有些巴洛克音樂的色彩,卻陰錯陽差的留在不少觀影人的記憶中,成為一場美麗的誤會。

Randall Meyers的名字也因此跟這部影史不朽的鉅作(得了快九項奧斯卡啊),奇妙的連結在一起。

當年冷調沉默的考古學家,在營火晚會凝視著述說希羅多德《歷史》的知性女子─卻未體認到不可踰越的邊界之存在。英倫情人的演員們後來在2016年的羅馬電影節重新合體[連結]。即使要角的容貌隨歲月轉變,神采彷彿還說著故事。「且就虛無醒世夢,返於曲折復人情」。回想電影與現實的虛實重合,多少是感觸? 多少是投射? 比例只有觀影者,本身能夠衡量。

2019/8/29

SQL Pivot 範例


在SQL 2008以後的MSSQL中,PIVOT函數可將指定資料庫欄位的值產生分類小計後橫向展開,達到交叉表的效果。

舉例而言有個資料表叫做PLAN,裡面有兩個欄位 SCHOOL_NO,ACTION_CODE記載學校代碼與學校申請的項目。
若我們要知道每間學校每個申請項目的筆數,直覺會用 group by去小計,
但這樣查出來的結果還是一列一列的,並不會橫向展開。
select SCHOOL_NO,ACTION_CODE, count(*) group by SCHOOL_NO,ACTION_CODE 
 

清大 1 3 
清大 2 2 
清大 3 11 
政大 3 3 

可是一般正常人習慣看的,是將結果列出來的情形,比較清楚易懂。
     1 2 3 
清大 3 2 11 
政大 0 0 3 
 
筆者是從SQL2000開始學習的,以前必須先將結果 用case when ACTION_CODE = '2' then count else 0 的方式,
將每一個可能的結果擺到橫軸顯示。
但在SQL 2005以後提供了pivot函數,就不需要這樣做(仍須看貴司DBA設定DB的相容等級>=90才能使用)。
以下面的範例,查詢區塊t先過濾出要彙整計算的資料集,
第一個欄位通常是學校或部門代碼
區塊p 則是告訴SQL 要用哪一個欄位計算小計
先輸入是要計算筆數或是加總
for 語法則讓您輸入要列出統計的欄位值,如果想看ACTION_CODE的值是1,2,3的
要寫成 [1],[2],[3]而不是一般 SQL 用兩個單引號包起來的樣式。
如果要顯示的是每月的薪資小計,就會是[1],[2]....一直列到12去了。


 SELECT c.SCHOOL_NAME, p.* 
 FROM (
  select  SCHOOL_NO,ACTION_CODE
   from PLAN  
   where PLAN_ID like'%1A%'
   --and STATUS in ('0','1','2')
 ) as t 
 PIVOT (
  count(ACTION_CODE) 
  FOR ACTION_CODE IN ([2],[21],[22])
 ) as p
 left join SCHOOL as c
 on p.SCHOOL_no = c.SCHOOL_NO
 where p.[2] >0 

如果選項非常多,又要手工輸入所有項目,感覺有點瞎?
這時候可以利用SQL內宣告變數搭配select語法,兜出字串再塞到 Pivot裡。


DECLARE @ParaList NVARCHAR(MAX), @PivotSQL NVARCHAR(MAX) 
 
SELECT @ParaList = COALESCE(@ParaList + ',' ,'' ) + QUOTENAME(SCHOOL_NO) 
FROM SCHOOL 
GROUP BY QUOTENAME(SCHOOL_NO) 

print @ParaList
完成版
/*宣告變數*/
 DECLARE @ParaList NVARCHAR(MAX), @PivotSQL NVARCHAR(MAX) 

/*用現有資料表欄位值組出分類列表*/
/*這裡不能用distinct,不然只會出現第一筆 */
SELECT  @ParaList = COALESCE(@ParaList + ',' ,'' ) + QUOTENAME(rtrim(ACTION_CODE)) 
FROM PROFESSION_PLAN  
group by ACTION_CODE
print  @ParaList

 /*將查詢語法改為一段TSQL,帶入參數後用sp_executesql執行*/

 SELECT @PivotSQL = N'
 SELECT c.SCHOOL_NAME, p.* 
 FROM (
  select  SCHOOL_NO,ACTION_CODE
   from PROFESSION_PLAN  
   where  PROFESSION_PLAN_ID like''%1A%''
   --and STATUS in (''0'',''1'',''2'')
 ) as t 
 PIVOT (
  count(ACTION_CODE) 
  FOR ACTION_CODE IN (' + @ParaList +  N')
 ) as p
 left join SCHOOL as c
 on p.SCHOOL_no = c.SCHOOL_NO
 where p.[2] >0 
 '
 
EXEC sp_executesql  @PivotSQL;

2019/8/3

窮查理的普通常識(增訂版)精華 poor Charlie's ALMANACK

《窮查理的普通常識》是巴菲特的投資夥伴─李察‧蒙格的作品,問世多年了。原文書名的ALMANACK是一個古字,原意有點像農民的農民曆,後來引申為年鑑或老生常談。翻譯者翻成普通常識似乎略微遜色,也許對台灣的讀者而言,稱作碎碎念更為適切。

本書分為譯者的評述,以及蒙格本人的演講集。摘錄本人覺得不錯的重點如次:


  • 遠離毒品、嫉妒;避免做事反覆無常、避免不借鑑前人的經驗。不要意志消沉。重視風險管理(我只想知道我會死在甚麼地方,這樣我就可以永遠不去那裏。)
  • 永遠反向思考。
  • 學會有承擔、可靠。作者認為麥當勞平凡但值得尊敬,她為數百萬少年提供第一份工作,讓青少年學會承擔工作的責任。


─第一講

  • 投資之前要學習數學、會計學、統計學、心理學的一些基本觀念,用比較寬廣的思想體系看待投資。
  • 規模經濟降低成本開銷,龐大的曝光率帶來資訊優勢與社會認同。但規模太大也有缺點,不夠專業。廣泛性報導的雜誌,營收可能輸給有專業需求的專門雜誌。縮小規模、加強專業化程度,能夠帶來巨大的優勢。
  • 組織太大變成官僚化、分工變成偷懶的藉口。官僚作風搞倒西屋電器。
  • 對於鄉村雜貨店被量販店打敗,不要有懷舊情懷與幻覺。
  • 要考慮規模與經營熱情加在一起時產生的威力,精簡、刻薄、效率會打敗企業競爭對手的官僚風氣。
  • 某些行業會爆發割喉戰,大者恆大;某些行業則人人賺錢,擠掉別人並不經濟。
  • 導入新技術不只要考慮降低當下成本,也要考慮幾年後的實質報酬。
  • 破壞性創新對行業可能是競爭性毀滅。
  • 股票投資要考慮自身理解能力的能力圈。
  • 贏家謹慎出手。
  • 投資顧問要績效,總是逼你交易她才有收入。可是現在是時機點嗎?
  • 不要迷信換股操作
  • 如何提升效率?→不以時數計算,以件或班次算,做完就回家。
  • 投資有偉大領導者的優質企業,靠他們幫自己賺錢。然後長期持有。
─第二講


  • 掌握學科的理論模型
  • 查檢表的威力



  • 跨領域
  • 善用不同學科知識來解決問題
  • 軟科學要模仿硬科學實事求是的鑽研精神,在學科精華的訓練要更嚴格,針對某些學科的基本原理必須熟記,以此去思考事物,若有衝突時要進行辯證。對於困難的東西不能逃避,學習者不論喜歡與否都必須熟練。

─第五講


投資者賺得財富,但秉持良知參與社會,幫那些信任自己的人掙錢。

2019/6/23

強制降低pdf 檔大小 (reduce PDF file size 2019)

工作上有個需求,是讓眾多的客戶將pdf上傳到指定的平臺。由於平臺使用租賃的虛擬機器,若不限制上傳大小,會造成web server很大的壓力,也造成日後備份的困擾。偏偏客戶上傳的有四、五百頁的pdf,單一檔案超過110MB,不禁讓人好奇,內容大都是文字與表格的pdf檔,大小為什麼會這麼驚人?

服務單位有授權專業版的 Acrobat,當中內建最佳化與縮減大小功能。可惜跑了很久,沒有甚麼效果。以坊間很多線上的pdf壓縮服務而言,大多是將圖層平面化、取消內嵌字型,或是將內嵌的圖檔降低品質後,另外寫入一個新的pdf檔。可是,他們都沒有用!

仔細想想客戶的需求,只是要將電子檔案上傳備查。文字內容是否可再編輯或選取,並不是重點。因此最後想出一個偏激的方法:把圖檔全部變成 黑白點陣圖格式(binary image,B&W)的 tiff檔,再變回pdf。這樣每一頁的大小從接近200K變成只有20k,頁面內的空白頁甚至變成0K。雖然看來是爛方法,但至少也是個解決問題的方法 >.<



※這樣會將每個頁面轉為黑白點陣圖,仍然可列印,但無法再選取文字內容或搜尋。類似將文件用事務機掃描的原理。
※只適用於錄案備查、檔案內容不再編輯的場合。

(1) 建好一個空資料夾,用來裝轉換後資料

(2)利用Acrobat專業版,點選檔案→轉存至 →影像→TIF


  (3)選擇步驟(1)的建好的資料夾,注意存檔類型是TIFF



  (4)在同一畫面,點選對話方塊下方的「設定」 
 (5)當中有三個選項,最底下的色域點單色,解析度選 118.11像素,要再降低檔案大小,可選59.06像素。



 (7)前述的轉換完成後,再點選Acrobat專業版的檔案→建立→合併檔案為一個PDF


 (8)點選「新增檔案」,選擇步驟(6)所看到的所有檔案。請注意檔案名稱的順序。


  (9)點下右上方的「合併」,頁面會一格一格反灰,直到都執行完為止。最後一個步驟請將合併完的檔案另存到您要的地方。
 (10)檢查檔案內容正確性。

2019/5/28

包生男?

豐臣秀吉自1586年開始「九州征伐」,過程中讓黑田孝高處理了已經歸順的城井鎮房,城井一家遭到謀殺。城井家在大友、島津、豐臣家之間游移,並不是甚麼稀奇的事,黑田父子的做法未免過分,據說他倆為此見到城井鎮房的幽魂,感到畏懼不安。這也是人情之常。

奇怪的是據說秀吉也對城井鎮房被害感到有點後悔,這就滿奇怪的。早年文化水平趨近於零的木下藤吉郎、羽柴筑前守,雖稱不上殺人如麻,但也沒有在少的,難道是真的對古老秘傳的弓術(艾蓬の射法)有興趣嗎?

後來想起平家物語的一段,不禁啞然失笑。

平清盛的女兒建禮門院得子貴為中宮,產下安德天皇,取禮記之義:國君世子生時,占卜結果為吉,射人以桑弧蓬矢六,射天地四方,才可以餵小寶貝吃飯飯。
禮記正義把桑弧蓬矢解讀成象徵男子要有經略四方的遠大之志是很重要的,「必先有志於其所有事,然後敢用穀也。」
這規矩從遙遠的唐土傳到高麗、日本,又從平安時代一直到十六世紀,儒家色彩的意義淡薄了,儀式性的成分變多了,幾經流傳至民間,或許巫術的色彩更濃厚了一些。城井家是鎌倉時代就延續下來的氏族,累積一些「文化資產」,引以自豪,城井鎮房還曾得意洋洋地去教幕府將軍足利義稙艾蓬是在射甚麼碗糕,帥!

後來意氣風發的秀吉大人所求皆得,滅掉一個見風轉舵的城井家,老實說也不怕九州的情勢有所變化。先要城井家把家寶小倉色紙跟領地交出來,當然是政治上的借題發揮。

但他的軟肋是愛面子,又膝下猶虛。
殺了人才後悔,大概是因為他從哪裡聽來桑弧蓬矢的片段,把「生男子」的儀式搞成「包生男」的祕法,
才會對一個九州小大名斷送性命,感到微微的惋惜吧。

再認真想想,他沒學到這個秘傳,也許是件好事
──幾百年前,年幼的安德天皇因為平家戰敗了,被外祖母二位尼抱著,投入萬里波濤。雍容華貴的婦人,指著大海,告訴小男孩萬里之下也有帝都時,會不會想起那眾人擁簇、「射天地四方」的一刻?


國君世子生,告於君,接以大牢,宰掌具。三日,卜士負之,吉者宿齊朝服寢門外,詩負之,射人以桑弧蓬矢六。射天地四方,保受乃負之,宰醴負子,賜之束帛,卜士之妻、大夫之妾,使食子。

2019/5/21

c# 列出所有類別中的屬性 ( Iterate through all class fields in C#)

I have  one example class like this:

public class Foo{
 public string Idno { get; set; }
 public string Phone{ get; set; }
public string Department{ get; set; }
}

 In order to bind database's  columns like EF,  I would like to iterate through these fields dynamically




using System.Reflection;



   Foo foo = new Foo();
            foo.Idno = "a12345678";
            foo.Department = "IT";

            foreach (PropertyInfo prop in typeof(Foo).GetProperties())
            {
                Response.Write(prop.Name + ";" + prop.GetValue(foo, null));
            }

2019/5/4

存股的心理素質

身為上班族,存錢是非常困難的,而存股需要定期投入部份資金,更是困難。所以有幾個規則必須遵守。如此一來平常查看持股,常常是不漲不跌,感覺非常無聊,但您可以放心睡個好覺。

審慎掌握公司的營業本質。
電子股業界競爭淘汰很大,對產業生態系不了解者,實在不建議購買。此外這些產業亮點外資介入多,漲、跌的點都不是一般投資人容易掌握,除非有認真研究,不然更不適合存股操作。
股利後務必要逢低再投入
存股是希望擴大單位數(張數)以換取更多的配息,才有複利效果。
接近除權息再來盯價
如果選中的標的沒有很大的波動,每年接近除權息再來盯價,就是最低價。如果不是熱門股,除息完通常還會再跌一點點。
不借錢買股
作股票要用閒錢。股票市場比起其他的生意而言沒有保證收益,資金動用若有時間壓力,遇到下跌會感覺股利遲遲不來,會加大心理壓力。
好股票通常不會便宜
好股票通常不會便宜,下跌是出了事才會便宜。弄清楚出事是偶然波動還是傷筋斷骨,以免誤上賊船。
如果買入的股票都是體質良好的股票,而您不借錢買股,就很少會需要煩惱要不要停損的問題。

2019/3/29

存股的技術─如何找到好的存股對象( How to invest in the Taiwan stock market like Warren Buffett; similar time deposit stocks)

自從銀行利率持續低落與被動收入觀念盛行後,如何透過投資創造財務現金流,成為顯學。從100年開始自己繳了不少學費買書研究,洪瑞泰、溫國信、郭際勝、林茂昌四位先生的著作對我觀念影響甚大。投資業績經營蒸蒸日上又低調賺錢的公司,讓經營團隊定期把利潤回饋給我們,不要賠錢;這才應該是投資的本質。林茂昌先生的「我的職業是股東」用很平淡簡明的文字呈現這個理念,個人奉為圭臬。

但這些股票實在很低調,到底要如何累積一個自己的投資組合,伺機出手?
剛好有同事在問,順手分享。

一、準備:建立名單

平常吃飯看新聞,遇到喜歡但買不起的牌子,訓練自己去搜尋他的原廠或代理是誰?在臺灣有無上市櫃?
財經台的「休閒時段」有時候會介紹一些台灣小廠商的故事,有看到就做筆記。
但看到「分析師」報的則立刻轉台。商X周刊報的專題報導有時介紹一些新興企業或潛力股,美化作文的成分不少,內容要打七折來看。
慢慢累積自己喜歡的股票清單,存在Evernote這類線上筆記裡;定期拿出來看看當初的眼光對不對;檢討看走眼的原因為何。

二、初步過濾

利用yahoo 股市 (網頁版,手機板不好用)查股價 由月線看現在股價在歷史股價的相對位置,
   確認股價是在下跌或上升段。若已重跌過但持續三季業績回溫則可考慮。

再點選「基本」
  • 確認資本額至少5億以上
  • 在12月左右看最新四季每股盈餘, 由最近三季每股盈餘求平均再 *4; 推估該年度全年 eps。  這個eps 再乘以0.7 大概是可能會配發的股利。
  • 看看最近四年每股盈餘是否穩定成長;

三、給我股利其餘免談

觀察最近五年是否都能穩定配發股利 ,歷年股利是否達到該年度eps的七成以上
  • 公司再怎麼好,不能給我股利,我賺不到錢啊!所以股利每年劇烈變動者不考慮
  • 以現金股利為主;配股會稀釋股本
  • 若差距太大代表公司還是辛苦賺錢甚至借錢發股利,或有難言之隱(潤泰新2018年大賺eps7元但股利才2元),謹慎考量!
  • 殖利率至少5以上。少於五的除非是傳說中的上古神器「種花電信」,有各大基金護盤可做為資產避險配置的一部分,不然不考慮。2019年3月的現在台股上萬點,還是有許多好的高殖利率股可以挑。


、考慮個股所屬產業的性質與市場佔有度。

  1. 營業性質(金融、醫藥、新創、海外貿易、高資本投資的資訊研發業  請遠離)
    ※容易受到匯損、專利訴訟、市場流血競爭的震盪
    像工具機之前商X周刊報得跟神一樣,但遇到匯損或貿易戰慘兮兮,
    如1540喬福,之前曾抱一百萬,膽戰心驚。
  2. 公司信譽(專注本業,不要像某碳粉匣廠去投資飯店...)
  3. 品牌形象(卡拉歐K、柚木家具)
  4. 進入障礙(重金屬、上流原物料供應商;生產大廠需應付嚴格稽核環境汙染控制措施)
  5. 佔有率 (已站穩腳步,大盤短期漲跌跟我沒關係)
  6. 奸商指數(政府標案、黨國遺產、特許事業) =>能躺著賺,代表能守住你的錢 =>但還是要注意公司經理人制度是否健全,滿足上述第2項
  7. 體質變化:這是最難看的部分。如2019年4月中連貨運獲利從1.5億元縮水到1,500萬元,大舉裁員;105、106年EPS都不到1元,107年元卻配股3.75元。錢從何處來??

五、配合「財報狗」的選股功能,幫忙做財報數據的檢核。

以往的做法都是開一個Excel,把各項數據貼進去拉公式加加減減。
現在完全自己蒐集數據與判讀的話,實在太麻煩了,
建議使用財報狗的選股功能,
選股 https://statementdog.com/screeners/custom 的自訂選股,設定條件

  • 流動比率近五年平均大於150%
  • EPS近五年平均大於1元
  • 股價淨值比目前小於2倍
  • 負債比率近五年平均小於30%
  • ROE近五年平均大於15%
  • 每股自由現金流近五年平均大於1元


個人偏好過濾出 50元以下、尚未起漲的股票,可以殖利率6以上,可存股的明日之星。

參酌上方1-4點的過濾條件,再點左方的股票健檢(排除地雷股健診、定存股健診、成長股健診、便宜股健診),可以快速看過他的情形,作為下單前的最後參考。其他的診斷指標需要付費,但因為是月結,可以考慮在除權息的那一兩個月再開通使用(哈,財報狗的版大看到不要怪我。..)這樣好像請了一位稽核人員在幫忙看,其實很不錯!


六、何時買。

若要再考慮選擇買點,溫國信先生認為股價符合平均股利的20倍可做為入手參考,平均股利的16倍以下則屬於便宜價,這是簡單易懂的判斷方法。

外,可利用 StockAI樂活五線譜或曾氏通道,判斷當下個股是否過高(過於樂觀、狂熱),作為輔助判斷基準。StockAI的作者是位財經統計跟資料視覺化、程式設計都非常厲害的高人,看他的網站非常迷人,就是功能多需要耐心找一下。有心的人請好好尋寶。

2019/3/5

黑金町

新竹火車站後站到竹蓮寺附近的地帶,舊地名叫黑金町。該地名由何而來,國史館台灣文獻館的劉澤民先生做過考證,該地名應為日式地名。劉氏利用辭書查得的 くろがねちょう  拼法,認定該辭的念法與常用念法不同,直譯應該是「黑鐵町」。所以推測命名來源是因為在鐵道附近而得名。嘉義、花蓮、屏東都有相近的町名。

以材質去聯想,軍艦進行曲的歌詞也有黑鐵(くろがね)。鐵道、軍艦以鋼鐵煉成,此理可通。
要更進一步尋求黑鐵與鐵道的關係的話,還是得從街町的命名之初去探索。台灣從大正2年就陸續有街町調整的消息。比起臺北、台南這些大都市,新竹是小地方,問題小得多。報載大正5年左右本來設置了一大堆「純母國色彩」的町名如城南橋通、旭町南門通、水田橋通、西門通、明石町、角町、隼町、....寺町、駿河町、黑金町、山手町等等。但後來這些町名並沒有完全使用,只有旭町、表町以及黑金町等幾個町付諸實行。

將傳統地名改為日式町名不是大人說改就改那麼簡單。從大正10年(1921)年  西川清瀾  的討論,可以看到時人對於此次更名的看法。當時的地籍資料是人工維護,辛苦完成的土地調查資料,倘若完全照新町名更正,工程非常浩大。假使有個臺北人到高雄買房子,町名改了,該如何更正臺北人手上的那份書狀,跟所有的統計書表呢?更何況取個有意義的好名字,讓大家都滿意,也很不簡單。再加上政治認同的問題,町名問題就更複雜了。以新竹的例子而言,有日籍委員認為既然要改的跟「內地」一樣,就改徹底一點,廳長倒是出來打圓場說,有改已經很好了,可以適度尊重一下地方的意見。到1920年代,民族意識萌發,總督府對町名的政策似乎有所放寬,又說町名改正方針是「舊稱呼尊重は機宜に適す」,因地制宜隨機應變。

閒話休提,在西川清瀾的討論中,適巧提到鐵道與黑金町的關係。以當時人的語言習慣,與鐵道相關的地名命名,直覺就想到黑鐵。原文段落大意如下:

日本時代的鐵道部所在(今日台鐵管理局舊址)本來叫「河溝頭」,若直接取名叫 くろがねちょう(黑鐵町),有點太老派;如果叫做「天馬町」也不錯,顯示出風馳電掣的感覺。「火車町」應該比較能受到台籍人士支持,但在佛教用語中,「火車」一詞可一點都不OK, 火車+地獄是不祥之名,畢竟「以火車迎載並轢殺罪人之地獄 」感覺像在看與神同行....後來拍板定案挑了泉町,因為鐵道是文明開化的泉源。皆大歡喜。

亂看一通,意外找到「黑金」的源頭。哎呀,文字真是太有趣了。

2019/2/14

Entity Framework 裡的View,顯示結果不正確 (Entity Framework returns incorrect data from SQL Server view)

我們的專案中,針對某些join非常複雜且使用lambda不易除錯的報表,會先在SQL Server上寫成View或預存程序來呼叫。但某隻報表卻出現奇怪的狀況,原來View的資料是對的,在C#  Entity FrameWork程式碼內下中斷點,看到程式產生的SQL也是對的,但輸出的結果卻荒腔走板。

View的內容只是幾個Table的組合,沒有特別的地方
select COMPANY_CODE,  COMPANY_NAME,  GOODS from SELL_RECORD

1,蘋果,  IPAD
1,蘋果,  IPHONE
2.HTC,  HTC ONE

在EF內則變成

2,蘋果,  IPAD
2,蘋果,  IPHONE
2,HTC,  HTC ONE

後來查了文章  [出處1] [出處2],問題在於查詢的欄位內有COMPANY_CODE這個欄位是查詢結果相關table的第一個主索引鍵,但並不是 Query 結果的真正索引鍵。而Entity FrameWork在將查詢結果轉為物件的過程中,需要在查詢結果內找到有意義的Key值,任其自行推斷會發生恐怖的不測。

最後我們使用 SQL 2005以後即具備的 ROW_NUMBER 方式幫記錄排序,並產生流水序號CID供EF判斷。也別忘了在EF的模型檢式介面,手動將此欄位設定為主索引鍵並重新建置,才能發揮作用。

 ROW_NUMBER() OVER(ORDER BY SomeValue) AS CID

2019/1/13

使用chart.js 畫系統監控圖表

專案有個需求是可以觀察server 上資源的使用情形。本來習慣使用 hichart,但後來發現他的使用是要錢的,於是改用chart.js。
繪製動態圖表需要準備幾件事情:
一、取得資料來源:目前多用ajax取得資料。
二、資料有無依照時間序列變化:資料可能是依照時間變化跑的,或者只是依類別顯示。
三、要幫資料歸類出x軸(資料點的名稱)與y軸(數值變動)。

我們的專案是利用power shell 或 vbs 將伺服器監控的數據寫到SQL Server,再用Asp.net 網站讓管理人員查閱資料。作一隻簡單的泛型處理函式(ashx)將資料轉為json,讓chart.js讀取。

我們當初在紀錄資料時,每筆紀錄就包含日期、CPU使用率跟可用記憶體。很明顯這是隨時間序列變化的資料。搭配EF大概是這樣寫:

 using ( xxxxxxxEntitiesdbm = new xxxxxxxEntities()) {
                string vid="OOOp_WEB";

                /*抓兩天以內的資料*/
                DateTime lastdate = DateTime.Now.AddDays(-2);

                var query1 = dbm.monitor_record
                    .Where(o => o.Server_id == vid && o.Recdate >= lastdate)
                    .Select  ( o=> new{
                       x = o.Recdate,
                       y = o.CPU_Useage,
                       z = o.Available_Memory
                    }
                    ) .ToList();
                string vv = JsonConvert.SerializeObject(query1);
                context.Response.Write(vv);         
            }

然後 chart.js的範例是參考Line (point data)的做法:
https://www.chartjs.org/samples/latest/scales/time/line-point-data.html

網頁須載入以下的js元件跟jquery。
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
<script src="https://www.chartjs.org/dist/2.7.3/Chart.js"></script>
<script src="https://www.chartjs.org/samples/latest/utils.js"></script>


不過問題來了,我希望從ajax抓取資料,這點跟範例不同。由於ajax預設為非同步,相關事件是包在success的區塊內,因此修改成有結果再把資料傳給另一個函數繼續顯示。

/*以下的 javascript是放在載入頁面中*/

window.onload = function() {
    $.ajax({
        url: "../WebAPI/Hardware.ashx",
        type: "POST",
        data: {
            ENCODED: "1",
        },
        dataType: "json",
        success: function (Xresponse) {
            DrawChart(Xresponse);
        },
        error: function () {
            alert("無法載入。");
        }
    });
};


我的原始資料雖然能順利取得json,而且也帶有類別標籤x跟y,但直接帶到範例內的datasets ,無論怎樣都無法直接顯示。




看看原來範例,x是日期而y是數值,我並沒有搞錯啊?看來可能是解讀json的問題。不論陣列轉 json (array/object to json ) 的 JSON.stringify() 或 json轉陣列的 JSON.parse()都是過了,chart.js還是認不到資料。


後來爬文的結果,應該利用foreach 將資料拆開成三個陣列:

陣列一存資料標籤
陣列二存第一條線的數值
陣列二存第二條線的數值

利用javascript中陣列 push 新增元素的方式實作出來
   var labelsx = [], dataCPU = [], dataMEMORY = [];
        for (var rr in results) {
            labelsx.push(results[rr].x);
            dataCPU.push(parseFloat(results[rr].y));
            dataMEMORY.push(parseFloat(results[rr].z));
        }

接下來就能將資料以標準陣列的方式餵給chart.js



然後這個圖表包含cpu使用率跟記憶體,兩個y軸的數據差距很大,所以需要左右兩邊不同刻度的y軸。

大功告成,這樣圖表就會顯示出來了。