飛艷小屋

          程序--人生--哲學___________________歡迎艷兒的加入

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            52 Posts :: 175 Stories :: 107 Comments :: 0 Trackbacks

          常用鏈接

          留言簿(85)

          隨筆檔案(52)

          文章分類(157)

          文章檔案(174)

          相冊

          .NET方面的網站

          常上的網站

          建網站用的網站

          有關java的技術網站

          真正能用得上的網頁空間

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

           

          (一).內容

             在操作Excel的過程中遇到了一些問題. 比如: 訪問Com組件權限,無法讀取Excel等
             文章描述了怎樣雙向操作(讀取和生成)Excel文件,以及怎樣解決遇到的問題!

          (二).代碼
             開始時用了下面兩個方法進行生成和讀取 Excel:
             1.生成Excel文件方法一:
                ' <summary>
              '  下載Excel方法1(用流實現)
              ' </summary>
              ' <param name="dt">要轉換為Excel文件的表</param>
              ' <param name="page">頁面Page對象,用法: 將me.Page傳遞過來即可</param>
              Public Sub DownLoadExcelToClient1(ByVal dt As DataTable, ByVal FileName As String)
                  Dim resp As HttpResponse
                  resp = Page.Response
                  resp.ContentEncoding = System.Text.Encoding.Default

          'System.Text.Encoding.GetEncoding("GB2312")
                  resp.AppendHeader("Content-Disposition", "attachment;filename=" + FileName)
                  Dim colHeaders As String = "", ls_item = ""
                  Dim i As Int16 = 0

                  '取得數據表各列標題,各標題之間以\t分割,最后一個列標題后加回車符
                  For i = 0 To dt.Columns.Count - 2
                      colHeaders += dt.Columns(i).Caption.ToString() & Chr(9)
                  Next
                  colHeaders += dt.Columns(i).Caption.ToString() & Chr(13)
                  '向HTTP輸出流中寫入取得的數據信息
                  resp.Write(colHeaders)

                  Dim row As DataRow
                  '逐行處理數據  
                  For Each row In dt.Rows
                      '在當前行中,逐列獲得數據,數據之間以\t分割,結束時加回車符\n
                      For i = 0 To dt.Columns.Count - 2
                          ls_item &= row(i).ToString() & Chr(9)
                      Next i
                      ls_item &= row(i).ToString() & Chr(13)

                      '當前行數據寫入HTTP輸出流,并且置空ls_item以便下行數據    
                      resp.Write(ls_item)
                      ls_item = ""
                  Next
                  '寫緩沖區中的數據到HTTP頭文件中
                  resp.End()
              End Sub
             2.讀取Excel文件
               ' <summary>
              '  讀取Excel文件
              ' </summary>
              ' <param name="dt">要轉換為Excel文件的表</param>
              ' <param name="page">頁面Page對象,用法: 將me.Page傳遞過來即可</param>
              ' <return>數據集DataSet</return>
              Public Function ReadExcelFileToDataSet(ByVal strFileName As String) As DataSet
                  Try

                      '建立一個專門存放Excel文件的目錄
                      If Directory.Exists(Page.Server.MapPath("ExcelFolder")) = False Then
                          Directory.CreateDirectory(Page.Server.MapPath("ExcelFolder"))
                      End If

                      Dim strConn As String
                      strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" &

          Page.Server.MapPath(".") & "\ExcelFolder\" & strFileName & ";" & "Extended

          Properties=Excel 8.0;"
                      Dim conn As OleDb.OleDbConnection = New OleDb.OleDbConnection(strConn)
                      Dim strExcel As String = "select * from [sheet1$]"
                      Dim ds As DataSet = New DataSet
                      conn.Open()
                      Dim adapter As OleDbDataAdapter = New OleDbDataAdapter(strExcel, strConn)
                      adapter.Fill(ds)
                      Return ds
                  Catch ex As Exception
                      Throw ex
                  End Try
              End Function

             生成是成功的,但讀取不成功,提示:"數據源格式有誤!"
             一直是認為:ReadExcelFileToDataSet方法有誤,調試了半天,找了N多資料也不能成功!
             后來經過"時間的流逝",終久確認第二個方法沒有錯誤,是完全正確的,是第一個方法
             生成格式的問題. 于是我將第一個方法換為下面的方法,讀取和寫入就OK了.
           
           3.生成Excel文件方法二:
               ' <summary>
              '  下載Excel方法2(用office-Excel-Com組件對象實現)
              ' </summary>
              ' <param name="dt">要轉換為Excel文件的表</param>
              ' <param name="page">頁面Page對象,用法: 將me.Page傳遞過來即可</param>
              Public Sub DownLoadExcelToClient2(ByVal dt As DataTable)
                  '生成Excel操作相關對象
                  Dim xlApp As Excel.Application
                  Dim xlBook As Excel.Workbook
                  Dim xlSheet As Excel.Worksheet
                  xlApp = CType(CreateObject("Excel.Application"), Excel.Application)
                  xlBook = CType(xlApp.Workbooks.Add, Excel.Workbook)
                  xlSheet = CType(xlBook.Worksheets(1), Excel.Worksheet)


                  'xlSheet.Range("A1:B1").Merge(0) '合并單元格
                  'xlSheet.Cells(1, 1) = "員工資料信息:"

                  '賦標題(Excel文件中的標題)
                  Dim rowIndex As Integer = 2
                  Dim colIndex As Integer = 0
                  Dim Col As DataColumn
                  Dim Row As DataRow
                  For Each Col In dt.Columns
                      colIndex = colIndex + 1
                      xlApp.Cells(rowIndex, colIndex) = Col.ColumnName
                  Next

                  '將表dt的所有行寫入xlApp對象(Excel文件中的內容)
                  For Each Row In dt.Rows
                      rowIndex = rowIndex + 1
                      colIndex = 0
                      For Each Col In dt.Columns
                          colIndex = colIndex + 1
                          xlApp.Cells(rowIndex, colIndex) = Row(Col.ColumnName)
                      Next
                  Next

                  xlSheet.Application.Visible = True   '置為可見

                  '建立一個專門存放Excel文件的目錄
                  If Directory.Exists(Page.Server.MapPath("ExcelFolder")) = False Then
                      Directory.CreateDirectory(Page.Server.MapPath("ExcelFolder"))
                  End If

                  '刪除服務端臨時文件: download.xls
                  If File.Exists(Page.Server.MapPath(".") & "\ExcelFolder\download.xls") = True Then
                      File.Delete(Page.Server.MapPath(".") & "\ExcelFolder\download.xls")
                  End If

                  '在服務端保存download.xls
                  xlSheet.SaveAs(Page.Server.MapPath(".") & "\ExcelFolder\download.xls")

                  '殺死Excel進程
                  Dim myproc As System.Diagnostics.Process = New System.Diagnostics.Process
                  Dim proc As Process
                  Dim procs() As Process = Process.GetProcessesByName("excel")   '得到所有打開的進程
                  Try
                      For Each proc In procs
                          If Not proc.CloseMainWindow() Then
                              proc.Kill()
                          End If
                      Next
                  Catch
                  End Try

                  '這里用到個goto語句,是因為: 線程是異步執行的,下面的代碼要訪問download.xls文件,但有

          少數情況下上面的線程
                  '未能及時釋放download.xls文件的指針,那么下面代碼執行語句時會拋出異常, 當發生異常時

          需要等待資源釋放后,
                  '再重新訪問該文件, 保證下載文件能夠正確下載
          again:  Try
                      '輸出到客戶端()
                      If File.Exists(Page.Server.MapPath(".") & "\ExcelFolder\download.xls") Then
                          Dim TargetFile As FileInfo = New FileInfo(Page.Server.MapPath(".") &

          "\ExcelFolder\download.xls")
                          '清除緩沖區流中的所有內容輸出.
                          Page.Response.Clear()
                          '向輸出流添加HTTP頭 [指定下載/保存 對話框的文件名]
                          Page.Response.AppendHeader("Content-Disposition", "attachment; filename="

          + Page.Server.UrlEncode(TargetFile.Name))
                          '向輸出流添加HTTP頭 [指定文件的長度,這樣下載文件就會顯示正確的進度
                          Page.Response.AppendHeader("Content-Length", TargetFile.Length.ToString())
                          '表明輸出的HTTP為流[stream],因此客戶端只能下載.
                          Page.Response.ContentType = "application/octet-stream"
                          '發送文件流到客戶端.
                          Page.Response.WriteFile(TargetFile.FullName)
                          '停止執行當前頁
                          Page.Response.End()
                      End If
                  Catch
                      Thread.Sleep(10)
                      GoTo again
                  End Try
              End Sub
          這說明:
              a. 生成Excel文件后,用戶經過修改,還要反向讀取此Excel文件(比如:反向更新到數據庫中)
                 就只能用: 3 和 2方法結合使用. 
              b. 如果只是單向輸出Excel文件,用1和2方法都可以. 不過用2的話還要安裝Office-Excel,
                 一般還要設置一下Com組件訪問權限,添加對Com組件的引用: 添加: 引用->com->Microsoft Excel 11.0 object Library

          (三).不能讀取的原因 以及 權限問題解決

            a. 原因是:  方法 1 是用流的格式實現的,簡單的說它不是真正的Excel格式,而 3 是調用的
               Excel Com組件,生成的是真正的Excel文檔,所以能讀取(1也可以讀取,但也要用Stream類讀取,

              如果數據有些復雜的話,會很麻煩).  用1和3方法生成的文件及文件圖標一模一樣,并且用Excel 

              應用程序打開后顯示效果也是一樣的.  但當用記事本分別打開1和3生成的*.xls文件時,就明
               顯看到它們的不同了.(您可以下載一下本示例代碼程序,分別生成兩個文件,對比一下)

            b.在使用Excel com組件時除了裝Office-Excel以外,一般還要設置一下Com的訪問權限,步驟如下: 
               I.如果是Window2003 ->控制面版 -> 管理工具 -> 組件服務 ->
                 打開樹級目錄找到子目錄DCOM配置 -> Microsoft Excel 應用程序
                 -> 右擊選“屬性” -> 在彈出對話窗口中選“安全”選項卡->
                 -> 將啟動和激活權限設為自定義->點擊編輯按鈕->
                 ->在新窗口中將Everyone用戶加入,選中復選框"啟動權限",給予啟動權限

               II.如果是WindowXP ->控制面版 -> 管理工具 -> 組件服務(繁體為"元件服務") ->
                 打開樹級目錄找到子目錄DCOM配置 -> Microsoft Excel 應用程序
                 -> 右擊選“屬性” -> 在彈出對話窗口中選“安全”選項卡->
                 -> 將啟動和激活權限設為自定義->點擊編輯按鈕->
                 ->在新窗口中將Everyone用戶加入,選中復選框"遠程啟動",給予遠程啟動權限
          (四).使用Excel模板
                 雖然Com組件功能已經比較全面,可以對任意一個單元格設置和賦值.但是如果數據集DataSet比

             較復雜的話,全部用Com提供的方法實現就很麻煩了. 尤其是文檔頭和尾最難處理.
              這時可以這樣處理:
              a.先用Excel應用程序建立一個Excel文件,設置好頭/尾樣式和以及所有單元格的布局和格式
                (這里就是作用office 家簇的 excel進行表格布局,可以任意操作)   
              b.將此文件保存到工程的一個文夾下面即可.
                用法:
                只需將2中的:
                  xlBook = CType(xlApp.Workbooks.Add, Excel.Workbook)
                     改為: 
                  xlBook = xlApp.Workbooks.Add(page.MapPath(".") + "ExcelTemplate.xls")'使用現有模板
                即可。 這樣xlBook實際上是基于自己創建的模板的.
              這樣操作,一般表頭和標題列,表尾列一般不用設置,只顯示DataSet中的主要數據(甚至也不用顯

             示DataSet列名)

              最近給客戶做一些Excel報表,我們是這樣做的,直接把客戶給的Excel需求文件作為了模板.
              非常簡便,更爽的是這樣做報表跟客戶要求的完全相同。

          (五).代碼示例下載

             http://www.cnblogs.com/Files/ChengKing/OPExcel.rar

           此示例在配置環境:   WinXP(繁體) VS.net 2002    WinXP(簡體) Vs.net 2003 

                                              Win2003 VS.net 2003  測試能夠正確運行!

          相關文章:

          http://blog.joycode.com/ghj/archive/2005/01/12/42861.aspx
          http://cnbie.net/print_146048m63657.html
          http://blog.csdn.net/net_lover/archive/2004/06/08/6963.aspx
          http://dotnet.aspx.cc/ShowDetail.aspx?id=4EB79F05-B9A4-4E8A-836F-864393F40405
          http://dotnet.aspx.cc/ShowDetail.aspx?id=6AFBF00B-459D-4642-AD14-8A4765FFAFCC
          http://dotnet.aspx.cc/ShowDetail.aspx?id=8A4CBF47-B888-4832-3389-ED3A3A3C8AAB
          http://support.microsoft.com/kb/317881/EN-US/
          http://study.99net.net/study/program/vb/1049955696.html


                

          posted on 2005-12-08 13:51 天外飛仙 閱讀(635) 評論(0)  編輯  收藏 所屬分類: .net
          主站蜘蛛池模板: 乌拉特后旗| 泗阳县| 彭山县| 临清市| 连州市| 万安县| 泸定县| 岱山县| 屏山县| 武乡县| 原阳县| 汉源县| 邛崃市| 阿拉尔市| 长沙市| 旺苍县| 榆社县| 南和县| 衡水市| 辉南县| 固阳县| 大悟县| 柘城县| 乌拉特前旗| 南康市| 赣州市| 晋城| 嘉禾县| 库伦旗| 道孚县| 鄂伦春自治旗| 东阳市| 犍为县| 藁城市| 县级市| 延吉市| 达州市| 思茅市| 九龙城区| 焦作市| 遂平县|