2015年10月22日 星期四

[筆記]安裝IIS與簡易上線

安裝 IIS 7.5

在 Windows 7 Professional、Enterprise 或 Ultimate 上安裝 IIS 7.5

在VM中安裝Server 2012, MSSQL 2012, IIS(for aspx)


首先把Server 2012安裝起來

伺服器管理員→管理→新增角色及功能精靈→下一步直到「伺服器角色」
→勾選「網頁伺服器(IIS), 應用程式伺服器」→下一步到「功能」→勾選「.NET Framework 3.5功能」→下一步至「應用程式伺服器--角色服務」→勾選「網頁伺服器(IIS)支援」→新增功能下一步直到安裝完成
(安裝中提示輸入檔案來源時,將路徑指向CD:\Source\SxS)

::開始安裝SQL工具::
執行「setup」→安裝→「新增SQL Server 獨立安裝或將功能加入制憲有安裝」→確定→產品金鑰「XXX」→(跑一段安裝)→換對話視窗→下一步至「特徵」→勾選「Database Engine Services(細項隨意), 管理工具-基本, 管理工具-完整, 使用者連線SDK」→下一步至開始安裝

新增網站 & 預設首頁

  1. 進入「IIS管理員」
  2. 在「站台」→右Click「新增網站」→在「繫結」「IP位址」指定為本機IP
  3. 在剛新增的網站→切至「功能檢視」→「IIS」→「預設文件」雙Click進入設定→右Click「新增...」→輸入該目錄中的預設開啟頁

更新網頁

除了使用EEP的DataSource, 還有部分是使用VS原生的DataSource, 就要對連線字串稍作設定

遇到 HTTP Error 503. The service is unavailable

[NuGet]NPOI初探

從googlesite中搬過來的, 與其說介紹文, 比較像是個人「筆記」之類的存在
公司excel檔案都改成xlsx後, XLS相關就不再使用了
並沒有全面的介紹NPOI, 如果打算深入NPOI, 可以直接參考最底下的外部來源 

另一個與NPOI類似用途的工具:OpenXml 介紹

簡介 / 安裝方法
【簡介】
可以操作excel檔案的
Microsoft Developer Network > 學習園地 > CodePlex 教學

【安裝NPOI】
於VS中→右鍵網站或專案→管理NuGet套件→搜尋NOPI→安裝→完成
(沒錯, 就是這麼簡單)



XLS範例

使用的NPOI版本 v2.1.3.1 (供參考, 舊版本可能有部分程式碼不相容)

引入的參考

  1. using System.IO;  
  2. using NPOI.HSSF.UserModel;  
  3. using NPOI.HSSF.Util;  
  4. using NPOI.SS.UserModel;  

檔案IO

建立一個新活頁簿

  1. //建立物件  
  2. HSSFWorkbook workbook = new HSSFWorkbook();  
  3. workbook.CreateSheet("試算表A");  
  4.   
  5. //將物件寫到記憶體並產生另存  
  6. MemoryStream ms = new MemoryStream();  
  7. workbook.Write(ms);  
  8. Response.AddHeader("Content-Disposition"string.Format("attchment; filename=EmptyWorkbook.xls"));   
  9. Response.BinaryWrite(ms.ToArray());  
  10.   
  11. //清空  
  12. workbook = null;  
  13. ms.Close();  
  14. ms.Dispose();  

取出Server中已存在的活頁簿

  1. string strFilePath = string.Format(Server.MapPath(".") + "\\format_eCRF\\EmptyWorkbook.xls"); //抓取ASP.NET網頁的程式位址    
  2. HSSFWorkbook workbook;    
  3. using (FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.ReadWrite))    
  4. {    
  5.     workbook = new HSSFWorkbook(fs);    
  6. }  
  7.   
  8. /*--IT'S SHOW TIME!--*/  
  9.     
  10. //定番    
  11. MemoryStream ms = new MemoryStream();    
  12. workbook.Write(ms);    
  13. Response.AddHeader("Content-Disposition"string.Format("attchment; filename=EmptyWorkbook.xls"));    
  14. Response.BinaryWrite(ms.ToArray());    
  15.     
  16. workbook = null;    
  17. ms.Close();    
  18. ms.Dispose();  

cell操作 

建立cell

可以用CreateSheet / CreateRow / CreateCell串燒
(範例待續, 請先參考下方)

找尋目標cell

可以用GetSheet / GetSheetAt / GetRow / GetCell串燒到目標cell
(範例待續, 請先參考下方)


填入值

再用SetCellValue(value),可容許相當多種type

  1. //插入資料。  
  2. HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet("My Sheet"); //新建資料表同時插入  
  3. sheet.CreateRow(0).CreateCell(0).SetCellValue(0);  
  4. HSSFSheet at_sheet = (HSSFSheet)workbook.GetSheetAt(0);//用索引取得資料表並插入  
  5. at_sheet.CreateRow(0).CreateCell(0).SetCellValue("at sheet");  
  6. HSSFSheet _sheet = (HSSFSheet)workbook.GetSheet("試算表 A");   //用資料表名取得資料表並插入  
  7. _sheet.GetRow(0).GetCell(0).SetCellValue("get sheet by name"); 

欄位寬度
利用SetColumnWidth(第n攔, 寬度多少)
  1. workbook.GetSheetAt(0).SetColumnWidth(3, 2048);  

幫cell上色

物件HSSFCellStyle中的各項方法
  1. //建立儲存格樣式  
  2. HSSFSheet teststyle=(HSSFSheet)workbook.CreateSheet("sheet1");  
  3. HSSFCellStyle style1 = (HSSFCellStyle)workbook.CreateCellStyle();  
  4. style1.FillForegroundColor = HSSFColor.Pink.Index;  
  5. style1.FillPattern = FillPattern.SolidForeground; //版本2.0的操作方法  
  6.   
  7. HSSFCell cell = (HSSFCell)teststyle.GetRow(0).GetCell(0);  
  8. cell.CellStyle = style1;  

函數應用

在cell中產生與欄位相呼應的值

利用LastRowNum和LastCellNum取得陣列範圍
  1. for (int i = 0; i < workbook.GetSheetAt(0).LastRowNum ; i++)  
  2. {  
  3.     int n = 65;  
  4.     for (int j = 0; j < workbook.GetSheetAt(0).GetRow(1).LastCellNum; j++)  
  5.     {  
  6.         workbook.GetSheetAt(0).GetRow(i).GetCell(j).SetCellValue(Convert.ToChar(n + j).ToString() + (i+1));  
  7.     }  
  8. }  

Q&A

有些程式碼無法起作用

如果範例是以2.0以前的版本去實作,可能會遇到這些問題
【需要強制轉型】HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet("My Sheet");

【變更調用方法】style1.FillPattern = NPOI.SS.UserModel.FillPattern.SolidForeground;
建議下載官方範本去看該如何在C#中使用

CreateRow 和 GetRow 有何差異

相CreateRow想像成初始化Row會更容易理解
同:Sheet層的設定維持不變, 會在同一列(不會產生插入列的效果)
異:前者移除style後者保留, 前者Cell需要重新create cell後者維持




XLSX範例

基本上跟XLS很像, 遇到特別的再說

讀取樣板, 並另存新檔

只是能用而不太講究的話, 將HSSF全部改成XSSF就可以了
缺點是開啟檔案時, 會彈出警告視窗
參考官方範例並加以修改後(改成檔案是在記憶體中產生, 不留檔), 只要將下面這段
  Response.AddHeader("Content-Disposition", string.Format("attchment; filename=EmptyWorkbook.xlsx"));
  Response.BinaryWrite(ms.ToArray());

  workbook = null;
  ms.Close();
  ms.Dispose();
替換成這段就ok了(前半仍需完成HSSF替換成XSSF)
  Response.Clear();
  Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "editedWorkbook.xlsx"));
  Response.BinaryWrite(ms.ToArray());
  Response.Flush();
  Response.End();

將DataSet的資料用NPOI倒入Excel

如果有要特定格式, 可善用「string.format()」
例如日期:
  • 將「SetCellValue(column.ColumnName);」
  • 替換成「SetCellValue(string.Format("{0:yyyy/MM/dd HH:mm:ss}", row[column]));」
DataSet相關請參考:DataSet.Tables 屬性

/*--此處開始編輯檔案*/
  XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(2);

  for (int i = 0; i <= 2;i++ )
  {
      int rowIndex = i*3;
      
      dt = ds.Tables.Count > 0 ? ds.Tables[i] : new DataTable();
      XSSFRow headerRow = (XSSFRow)sheet.CreateRow(rowIndex);
      foreach (DataColumn column in dt.Columns)
    headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);

      foreach (DataRow row in dt.Rows)
      {
    XSSFRow dataRow = (XSSFRow)sheet.CreateRow(rowIndex+1);
    foreach (DataColumn column in dt.Columns)
    {
        dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
    }
    rowIndex++;
      }
  }




2015年10月13日 星期二

[JavaScript]可顯示英文大寫月份, 僅輸入時間可存完整datetime

在Actual Time僅輸入時間後, 能在DB中存入完整日期

DayDateNo.Actual TimeComments
1Dec/31/20151
2Jan/1/20162
5Jan/4/20163



【Read】(使用者要求要顯示MMM/dd/yyyy)
Actual Time:<asp:Label ID="D1Label" runat="server" Text='<%# Bind("D1","{0:HH:mm}") %>' />
Dosing Date:<asp:Label ID="CaptionD1" runat="server" Text="D1:"></asp:Label>
●後台
從後台撈資料出來後放入Json,再丟到前台進行格式化處理
由於涉及安全性,程式碼不完全公開
        DataTable dt = ds.Tables.Count > 0 ? ds.Tables[0] : new DataTable(); //將查詢結果放到DataTable
        string str_json = JsonConvert.SerializeObject(dt, Formatting.Indented); //將DataTable的內容轉換成JSON格式
        PdD.Text = str_json; //將JSON格式(文字)傳遞到前台

●前台
將抓到的月份轉換成使用者想看的
            calDate(); //呈現計算後的Dosing Date
         
            function calDate() { //日期計算
                var month = new Array(12);
                month[0] = "Jan";
                month[1] = "Feb";
                month[2] = "Mar";
                month[3] = "Apr";
                month[4] = "May";
                month[5] = "Jun";
                month[6] = "Jul";
                month[7] = "Aug";
                month[8] = "Sep";
                month[9] = "Oct";
                month[10] = "Nov";
                month[11] = "Dec";

                    var d = new Date(eval("jsonP[0].Period" + $("#lbPeriod").text() + "_dose"));
                    d.setDate(d.getDate() + Number($("#FormView1_CaptionD1).text()) - 1); //Dosing Date = Period + (Day-1)
                    var strD;
                    if (d.getFullYear() >= 2000)
                        strD = month[d.getMonth()] + "/" + +d.getDate() + "/" + d.getFullYear();
                    else
                        strD = "Undefined";
                    $("#FormView1_DateLabel").text(strD); //顯示使用者想看的格式
                }

藍字的:這時還是顯示數字,作用是依照Peroid與計算的天數差,顯示預計的日期
橘子的:將數字表示的日期,置換月份(js不自帶日期加減,需各自get再串接),>=2000的作用是避免使用者未設定日期(未設定日期的年份為19xx)

foreach的變化型就賣個關子啦


【Write】
1. 設定輸入欄位的屬性(多一個隱藏欄位)
Actual Time: <asp:TextBox class="HHmm" ID="D1TextBox" runat="server" Text='<%# Eval("D1","{0:HHmm}") %>' /></asp:TextBox>
Actual Time(隱藏的): <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("D1") %>'></asp:TextBox>

2. 隱藏欄位
將「 $(".HHmm").next().hide();」放在「  $(document).ready(function () { ... })」中

3. 利用「jquery.maskedinput.js」的功能來產生遮罩與限制輸入
            function setMasked() {
                $(".HHmm").mask("99:99", {
                    placeholder: "hh:mm", completed: function () {}
             });

4. 在「completed: function () { ... }」中放入輸入完成時要執行的動作,也就是當輸入完成時,將使用者輸入的稍加處理,放入實際上要回存DB的欄位
            $(this).next().val( //改變輸入框的值
              $(this).parent().prev().prev().children().text()  //抓取Dosing Date的日期
              + " " //在日期與時間之間加個空白
              + $(this).val() //取得使用者輸入的時間
            );

參考資料:JavaScript Date() 日期與時間

[EEP]發佈WinForm

開發工具:VS2012 Ultimate 2012
EEP版本:EEP2012 - SP5

修訂紀錄:

  • 2015-11-2 「後續更新」的部分補上Client Package;附上「Microsoft.VisualBasic.PowerPacks.Vs」的Microsof下載t網址

第一次發佈WinForm

【開發端】

開啟專案後,編輯「EEPNetClient」的「APP.config」進行設定
  ●如果開發端 = A/P server端


     <client>
        <wellknown type="Srvtools.LoginService, Srvtools" url="http://127.0.0.1:8989/Srvtools.rem"/>
   <wellknown type="Srvtools.ListenerService, Srvtools" url="http://127.0.0.1:8000/Srvtools.rem"/>
      </client>

  ●如果A/P server端在遠處,就修改「(ip address)」的部分 (可使用內網IP、固定IP等)
      <client>
        <wellknown type="Srvtools.LoginService, Srvtools" url="http://(ip address):8989/Srvtools.rem"/>
   <wellknown type="Srvtools.ListenerService, Srvtools" url="http://(ip address):8000/Srvtools.rem"/>
      </client>

右鍵「EEPNetClient」的專案→「屬性 (Alt+Enter)」→「發行 / Publish」
  指定要發行此應用程式的位置:用「瀏覽」來選擇位址
  設定「發行位置 / Publish Location 」的位址,可指定資料夾或用IIS (訪問權限:讀取,   應用程序權限:腳本)
  進入「應用程式檔案 / Application Files...」
    確認這五個檔案「EnvDTE.dll, EnvDTE80.dll, InfoRemoteModule.dll, Srvtools.dll, stdole.dll
     ├發行狀態 / Plublish Status:包含 / Inclued
     └下載群組 / Download Groups:必要項 / Required
  進入「必要條件 / Prerequisites...」
    至少將下列勾選元件勾選
     └Microsoft .NET Framework 4 Clinet Profile (x86 和 x64) 以及適用於 .NET Framework 4 的更新 (KB2468871)
    如果有使用到報表 / Report,請示需求勾選(RDLC 或 Crystal Report)
     ├Microsoft Report Viewer 2012 Runtime
     └SAP Crystal Report Runtime for 4.0 ※如找不到,則下載RunTime, CRforVS_redist_install_x64_x86_130.5,於使用者端安裝)
    設定「指定必要條件的安裝位置 / Specify the install location for prerequisites」

     └從應用程式的相同位置下載必要條件 / Download prerequisites from the same location as my application
      ※由於目前開發安裝來源皆為相同版本的A/P Server, 如果需安裝插件與A/P Server不同時,才需要選第3項進行指定    
  進入「更新 / Updates...」
    如果不希望使用者每次改版都重新安裝,就需要將「應用程式應該檢查更新檔 / The application should check for updates」勾選
    其餘設定可參考圖片
  進入「選線 / Option...」
    


利用「發行精靈 / Publish Wizard」來發行(必須先設定完「應用程式檔案」與「必要條件」),可依更新需求選擇不同的方法
不具有更新功能
  1. 您要將應用程式發行至何處? 「瀏覽」要存放的位置
  2. (下一步)
  3. 使用者要如何安裝應用程式? 「從CD-ROM 或 DVD-ROM」
  4. (下一步)
  5. 應用程式會在哪裡檢查更新檔? 「應用程式將不會檢查更新檔」
  6. (下一步)
  7. 已完成發行的準備工作
  8. (完成)
需要更新功能
  1. 您要將應用程式發行至何處? 「瀏覽」要存放的位置
  2. (下一步)
  3. 使用者要如何安裝應用程式? 「From a Web site」→用「瀏覽」去指定資料夾
  4. (下一步)
  5. 是否可以在離線時使用應用程式?是,這個應用程式可於線上或離線時使用 (ry)
  6. (下一步)
  7. 已完成發行的準備工作
  8. (完成)
※發行完,就可以將APP.config的設定換回開發端的IP,否則在內測時會連到A/P端

【A/P端】

有使用連線更新時,還須設定IIS。不過此處只針對EEP的部分
※EEP的DLL有更新(通常是Srvtools)或初次安裝時,才需要執行此步驟  

開發端同版本的EEP中,複製「EEPNetClient」「EEPNetServer」InitEEP」這3個資料夾於至A/P端(例如「E:\EEP2012」)
  以系統管理員身分執行「InitEEP.exe」
設定資料夾路徑後,點下「Apply」保存,再點「Install GAC」
    Server Directory: EEPNetServer的path
    Client Directory: EEPNetClient的path
    WebClient Directory: (只有WinForm時,可以不用設定)
  系統管理員身分執行「EEPNetServer.exe」
    「System」→「DB Manager」→在Dialog「Database Manager」中「新增 / Add」或「修改 / Modify」DB連線字串
      DataBase Name: 
      DataBase String: ex1 - 「User Id=userTest1; database=DBTest1; server=999,999,9,999; Connect Timeout=60
               ex2 - 「User Id=userTest2; database=DBTest2; server=.;Connect Timeout=60;Trusted_Connection=True
        [選項]Use Encrypt String: 加密連線字串, 建議勾選以提高安全性
      DataBase Type: MsSql
      Max Count: 20 
      Time Out: (隨連線字串改變)
        [選項]:Split System Table: 如果多個DB有共用EEP帳號時,請將此處打勾。各自獨立時不勾選
      Password: xxxxxxxxxxxxxxxxx
    設定完後,點「OK」,再點「Test Connection」確認連線。正常會顯示「Connect to database successfully
    如果無勾選Split System Table,而資料庫又是新建的需要設定範例時,點「Create System Table」→「Typical create」

    「System DataBase」的Tab,是設定以哪個DB做為Split System Table的依據。有勾選Split System Table的DB連線,其帳密驗證會以此處指定的DB為主。

掛載 / 更新 要使用的DLL
  【直接貼上檔案】將Server的DLL檔案放在「E:\EEP2012\EEPNetServer\專案名
    回到EEPNetServer主畫面,「System」→「Package Manager
    如果是新專案:Package的空白處右鍵「Add Folder」→選擇資料夾→確定
    舊有專案追加:點選既有的Package→下方按鈕「Add...」→選擇檔案→確定「Save」
      如果有勾選「Load in memory」,添加後需再點「Unload」和「Save」



帳戶與群組的權限設定
  如DB中已存在,可直接進行套用,不須再行設定
  詳細設定的部分請參閱「EEPManager」頁面 (暫無)

【使用者端】

第一次安裝
  執行「setup」→下一步到底
執行
  雙擊「EEPNetClient.application」

可能會碰到的問題
  安裝時
    - 顯示「程式已存在」或「安裝位置不符」:用控制台的「新增/移除程式」將EEP Client刪除
  執行時
    - 顯示「無法找到插件 (ry)」:將該組建的名稱與版本紀錄記錄下來,於Microsoft中取得並安裝

後續更新WinForm

(一般而言, 沒改動EEP控制項的DLL時(如Srvtools), Client的調整不須重新安裝
反之在無檢查更新的設定下, 使用者需再次Setup NetClient)

【開發端】 -- 有對EEPNetClient做修改才需要 (通常是有變更A/P端位址或EEP改版)
對「方案總管」中的「EEPNetClient」→右鍵「發行」
※如果大更動(如路徑改變, 追加必要插件),才需要到「屬性」中進行設定

【A/P端】-- 最常用到,特別是Client DLL的更新

可以直接覆蓋DLL, 但建議依照下列的方法
在開發端系統管理員身分執行「EEPManager.exe」
  「System」→「Package Manager」→選擇「Server Package」→將右側的DLL拖曳至左側進行更新

  「System」→「Package Manager」→選擇「Client Package」→將右側的DLL拖曳至左側進行更新

【使用者端】 -- EEPNetClient有變更才需要

不自動更新
  每次有更新時,需將Application Files資料夾中的檔案補齊,再執行「EEPNetCLient.application」

會自動更新
  直接執行「EEPNetCLient.application」,會自動檢查