2016年4月13日 星期三

Open XML SDK 利用範本產生WORD

因Office已經標準化成XML格式,要產出標準的Office 2007以上的格式就不可使用舊有的Office Library來產生,這次的專案需求是要利用一個範本檔(docx)作套表產出,是要複製範本的格式,依據資料筆數看要貼幾頁,找到此類別庫Open XML SDK來產出。
目前最新的版本是Open XML SDK 2.5是.NET4.0以上,因專案只到.NET3.5,故使用Open XML SDK 2.0版
Open XML SDK 安裝方式
  1. 手動下載方式
    • 下載位址2.5
    • 下載位址2.0
    • 預設安裝路徑為C:\Program Files (x86)\Open XML SDK\ 
    •  下載完有兩個檔案,一個是主要的DLL檔,另一個是他的工具,工具可以將Office檔案載入,可轉換C#的Code出來,幫你把產生此檔案的程式碼產出來,根本就是程式碼產生器,太方便了吧~~
    •  手動將此DLL載入(C:\Program Files (x86)\Open XML SDK\2.0\lib\DocumentFormat.OpenXml.dll)
  2. 使用NuGet
    • 在套件管理器輸入install-package documentformat.openxml,會抓取最新版,如要裝舊版的在後面加上-Version 1.0.0。
另外要再加入WindowsBase的.NET參考。

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

/// 
/// 複製範本並取出內容的部分
/// 
/// 
/// 
/// 
/// 
private void CopyWordFile(string fromWordFile, string toWordFile, out string templateText)
{
 if (File.Exists(toWordFile)) {
  File.Delete(toWordFile);
 }
 //
 File.Copy(fromWordFile, toWordFile);
 //
 using (WordprocessingDocument fromDoc = WordprocessingDocument.Open(toWordFile, true)) {
  templateText = fromDoc.MainDocumentPart.Document.Body.InnerXml;
  fromDoc.MainDocumentPart.Document.RemoveAllChildren();
 }
}

/// 
/// 設定WORD檔需要的參數
/// 
/// 
/// 
/// 
private void SetWordDictionary(string templateText, out string docText)
{
 Dictionary keyWordDict = new Dictionary();
 keyWordDict.Add("SEQTXT", 1);
 keyWordDict.Add("YEARXX", "105");
 keyWordDict.Add("DEPTNM", "部門");
 keyWordDict.Add("PLANNM", "計畫");
 keyWordDict.Add("DATEXX", "日期");
 keyWordDict.Add("BGTWTT", "金額");
 //
 ReplaceTemplateString(keyWordDict, templateText, docText);
}

/// 
/// 將WORD檔所設定的參數取代掉
/// 
/// 
/// 
/// 
/// 
private void ReplaceTemplateString(Dictionary keyWordDict, string templateText, out string docText)
{
 foreach (KeyValuePair item in keyWordDict) {
  Regex regex = new Regex(item.Key);
  templateText = regex.Replace(templateText, item.Value);
 }
 //
 docText += templateText;
}

/// 
/// 將XML的文字寫入到WORD檔
/// 
/// 
/// 
/// 
private void SetWordFile(string toFileName, string docText)
{
 using (WordprocessingDocument toDoc = WordprocessingDocument.Open(toFileName, true)) {
  MainDocumentPart mainPart = toDoc.MainDocumentPart;
  Body insertBody = mainPart.Document.AppendChild(new Body());
  insertBody.InnerXml = docText;
 }
}
在實作過程也遇到一些問題
  1. 當WORD檔裡有插入文字方塊時,複製出來的XML再貼回去產出來MSWord會說有錯誤,但強制開還是可以開。
  2. WORD範本檔在複製的時候,格式會有點錯亂,有的正常有的又不正常,後來我的WORD範本用Table來排版就比較正常,不知道是MSWord的問題還是Xml的格式問題。
參考文件:Creating Documents by Using the Open XML

2016年4月3日 星期日

Mac 打開檔案的應用程式,刪除重複的開啟程式

  1. 開啟Terminal.app,先輸入以下指令
  2. $ /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user
    
  3. 再輸入以下指令
  4. $ killall Finder
    
  5. 再重新開啟Finder點選打開的應用程式,重複的列表就會消失了
參考資料:http://hlchang.com/?p=817

2016年3月29日 星期二

SQL 取多筆欄位合併的寫法

如需要使用到一對多的資料查詢字串,例如一個學生一學期上過那些課,將課程串成一個字串該如何寫。
請教Google大神找到一個叫做For XML Path的作法
  1. 資料表有ClassTable、SubjectNameTable、StudentTable
  2. ClassTable
    • Year-學年
    • SubjectID-科目代碼
    • StudentNumber -學號
  3. SubjectNameTable
    • SubjectID-科目代碼
    • SubjectName-科目名稱
  4. StudentTable
    • StudentNumber-學號
    • StudentName-姓名

select StudentName, 
    STUFF((select ',' + RTRIM(SubjectName) from ClassTable
        inner join SubjectNameTable 
                           on ClassTable.SubjectID = SubjectNameTable .SubjectID 
        where ClassTable.Year=104 
            and ClassTable.StudentNumber = StudentTable.StudentNumber
        for xml path('')),1,1,'') as SubjectName from StudentTable
where StudentNumber='001'

2016年3月23日 星期三

建立SignalR網站

  1. 開啟VS2013,建立Web專案,選取MVC,變更驗證選不驗證。
  2. 開啟套件管理員執行Install-package Microsoft AspNet.SignalR  。
    • 注意安裝完的readme.txt,會說明修改的部分 
    • Scripts多出jquery.signalR-2.2.0.js,參考多出 Microsoft.AspNet.SignalR.Code及 Microsoft.AspNet.SignalR.SystemWeb 
  3. 新增一個資料夾名為Hubs
    • 在此資料夾新增一個項目選取SignalR Hub類別,取名為ChatHub.cs
    • 建完後將程式碼改成如下
  4. 新增一個Startup.cs的類別檔
    • 程式碼如下
  5. 開啟Controllers/HomeController.cs
    • 增加以下程式碼
  6. 在Chat上按右鍵,新增一個View
    • 程式碼如下
  7. 執行起來,用兩個瀏覽器開啟,一開始會先輸入使用者,接著看兩邊的訊息是否會互通。

參考來源: Getting Started with SignalR 2 and MVC 5

2016年3月21日 星期一

EntityFramework無法匯入View作為EDMX的實體

今天因需求需要匯入View到EF裡,發生匯進來後找不到實體,開啟EDMX的XML描述出現此訊息,
<!--產生期間發現錯誤:
警告 6002: 資料表/檢視 'Sal.dbo.test' 未定義主索引鍵。已推斷此索引鍵,並將定義建立成唯讀的資料表/檢視。-->

在這我們不去修改EDMX的XML檔,避免日後在更新時又會回復到原樣,我們還是採取在資料庫增加Key值的方式,看了保哥的文章才發現原來在view裡可以設定讓EF判斷此欄位為Key值得方式,在欄位上判斷ISNULL的方式:

SELECT          ISNULL(B02IDNO, '') AS B02IDNO, B02NAME, B02POINT, B02TPOINT
FROM              dbo.CPATemp

參考來源:解決 SQL Server 檢視表 (Views) 無法匯入 EDMX 的問題

SQLServer 連結伺服器別名

因專案上的需要要連結到其他SQLServer做查詢,因為對方沒有開具名管道所以我就使用IP做連結,剛好也是SQLSERVER所以在伺服器類型就選SQL SERVER,
因為原本要在View上利用此伺服器連結做資料查詢,但發現用IP的方式存檔SQLServer會自動把中誇號濾掉導致語法問題,所以只能用具名管道或是別名的方式設定此連結,因為對方沒開具名管道所以只能設定別名,設定方式如下:
  1. 連結的伺服器:設定想要連結的名稱 ,也就是別名
  2. 伺服器類型:選其他來源
  3. 提供者:SQL Server Native Client 10.0
  4. 產品名稱:可自行定義
  5. 資料來源:輸入IP
  6. 安全性頁籤則造常輸入

完成後側是看是否可正常連線。

2016年3月18日 星期五

SQL DBCC 陳述式

  1. 從計畫快取移除所有元素;指定計畫控制代碼或 SQL 控制代碼,從計畫快取移除特定的計畫;或是移除與指定的資源集區相關聯的所有快取項目。

  2. DBCC FREEPROCCACHE 
  3. 排清散發查詢對 Microsoft SQL Server 執行個體所用的散發查詢連接快取。

  4. DBCC FREESESSIONCACHE
  5. 釋出所有快取中所有未使用的快取項目。 SQL Server Database Engine 會主動在背景清除未使用的快取項目,讓記憶體存放目前的項目。 不過,您可以使用這個命令,以手動方式從所有快取或是指定的資源管理員集區快取中移除未使用的項目。

  6. DBCC FREESYSTEMCACHE('All')
  7. 從緩衝集區中移除所有的清除緩衝區。

  8. DBCC DROPCLEANBUFFERS
  9. 重組指定資料表或檢視的索引。

  10. DBCC INDEXDEFRAG(DBName,'TableName')
  11. 顯示指定資料表或檢視之資料與索引的片段資訊。

  12. DBCC SHOWCONTIG(TableName)
  13. 報告和更正目錄檢視中不準確的頁面和資料列計數。 這些不準確可能會使 sp_spaceused 系統預存程序傳回不正確的空間使用方式報表。

  14. DBCC UPDATEUSAGE(DBName)
參考資料 MSDN