顯示具有 OdsReaderWriter 標籤的文章。 顯示所有文章
顯示具有 OdsReaderWriter 標籤的文章。 顯示所有文章

2025年6月6日 星期五

[研究]用ProDotNetZip取代DotNetZip處理.ods

[研究]用ProDotNetZip取代DotNetZip處理.ods

2025-06-06

********************************************************************************

DotNetZip 最後版本 1.16.0

https://www.nuget.org/packages/dotnetzip/

This package has at least one vulnerability with high severity. It may lead to specific problems in your project. Try updating the package version.

This package has been deprecated as it is legacy and is no longer maintained.

此軟體包至少存在一個高危險漏洞。這可能會導致您的項目出現特定問題。請嘗試更新軟體包版本。

此軟體包已被棄用,因為它是舊版本,並且不再維護。

****************************************

上面畫面點右邊 Project website 後

https://github.com/haf/DotNetZip.Semverd
Please use System.IO.Compression! A fork of the DotNetZip project without signing with a solution that compiles cleanly. This project aims to follow semver to avoid versioning conflicts. DotNetZip is a FAST, FREE class library and toolset for manipulating zip files. Use VB, C# or any .NET language to easily create, extract, or update zip files.

請使用 System.IO.Compression! DotNetZip 專案的 fork 版本,無需簽名,可乾淨編譯。本專案旨在遵循語義版本控制 (semver) 以避免版本衝突。 DotNetZip 是一個快速、免費的類別庫和工具集,用於處理 zip 檔案。您可以使用 VB、C# 或任何 .NET 語言輕鬆建立、提取或更新 zip 檔案。

********************************************************************************

ProDotNetZip - NET Standard part of DotNetZip / Ionic's Zip Library
https://www.nuget.org/packages/ProDotNetZip

ProDotNetZip 沿用了 DotNetZip/Ionic Zip 原始程式碼,但僅限於 .NET Standard 部分,而非整個。命名空間保持不變,為 Ionic.Zip。

********************************************************************************

(完)

相關

[研究]用ProDotNetZip取代DotNetZip處理.ods
https://shaurong.blogspot.com/2025/06/prodotnetzipdotnetzipods.html

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite

2024年11月7日 星期四

[研究]NuGet 的 OdsReaderWriter 1.0.10 改用 OdsReadWrite.zip

[研究]NuGet 的 OdsReaderWriter 1.0.10 改用 OdsReadWrite.zip

2024-11-07

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

NuGet 的 OdsReaderWriter 1.0.10 的  License 是Copyleft,移除改用 odsreadwrite.zip

********************************************************************************

先用 NuGet 把 OdsReaderWriter 1.0.10 移除,然後把這篇的 OdsReadWrite.cs 拷貝放到方案中

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

(這篇的程式,以前是正常可用,但目前測試不能用,不知是否 System.IO.Compression 改版還是其他因素,待解決)

using 要變更

//using Zaretto.ODS;	// NuGet ODSReaderWriter 1.0.10 使用;
using OdsReadWrite;	// 若用 odsreadwrite.zip 中的 OdsReaderWriter.cs 檔案  

.cs 中

//ODSReaderWriter odsFile = new ODSReaderWriter();  // NuGet OdsReaderWriter 使用,注意大小寫不同
OdsReaderWriter odsFile = new OdsReaderWriter();  // OdsReaderWriter.cs 使用


因為 NuGet 安裝 OdsReaderWriter 1.0.10 會安裝 DotNetZip.Reduced 1.9.1.8,可移除。



編譯,看看有無問題,再進行處理。

(完)

相關

[研究]ASP.NET,WebForm,用 NuGet OdsReaderWriter 1.0.10 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-nuget-odsreaderwriter.html

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite






2024年3月30日 星期六

[研究]ASP.NET,WebForm,用 NuGet OdsReaderWriter 1.0.10 匯出 .ods

[研究]ASP.NET,WebForm,用 NuGet OdsReaderWriter 1.0.10 匯出 .ods

2024-03-30

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

發現 NuGet 提供 OdsReaderWriter 1.0.10,其實源頭也相同是 CodeProject 那篇,但是程式寫法有點不同;也不用自己另外手動安裝 Ionic.Zip 或 DotNetZip,會自動相依安裝。

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

GitHub - Zaretto/ODSReaderWriter: Open Document Spreadsheet reader writer
https://github.com/Zaretto/ODSReaderWriter
這邊直接下載 Code,敝人用 Visual Studio 2019 直接編譯是不能用。

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2



WebApplication1

正在安裝:

DotNetZip.Reduced.1.9.1.8

OdsReaderWriter.1.0.10



OdsReaderWriter 1.0.10
GPL-2.0-only

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets)
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
提供 odsreadwrite.zip

註:ChatGPT
The Code Project Open License (CPOL) 是由 The Code Project 社群發布的一種軟體授權。以下是關於 CPOL 的主要重點:
  • 寬鬆的授權:CPOL 允許用戶自由使用、修改和分發軟體,不論是二進位形式還是原始碼形式。
  • 不要求開源:與 GPL 等授權不同,CPOL 不要求衍生作品必須開源。您可以在專有項目中使用 CPOL 授權的代碼,而不必公開自己的原始碼。
  • 歸屬要求(Attribution):在分發軟體或衍生作品時,必須給予原作者適當的歸屬。
  • 免責聲明:該授權通常包括免責聲明,表示軟體是“按原樣”提供的,沒有任何保證。
總結來說,CPOL 允許您在遵守歸屬和免責條款的前提下,自由使用、修改和分發軟體,而無需開源您的代碼。

********************************************************************************

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="MyDBConnectionString" connectionString="Data Source=127.0.0.1;Initial Catalog=MyDB;User ID=sa;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="TempFolder" value="D:\Production\TempImageFiles\" />
  </appSettings>
</configuration>


Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication2.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:SqlDataSource ID="SqlDataSource_Field2" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="SELECT N'全部' AS [Field2], 0 AS Priority
            UNION
            SELECT DISTINCT [Field2], 1 AS Priority FROM [MyTable] ORDER BY Priority, [Field2]"></asp:SqlDataSource>
        <asp:DropDownList ID="DropDownList_Field2" runat="server"
            AutoPostBack="True" DataSourceID="SqlDataSource_Field2"
            DataTextField="Field2" DataValueField="Field2">
        </asp:DropDownList>
        <br />
        <asp:Button ID="Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip" runat="server" Text="匯出(.ods)"
            OnClick="Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click" /><br />
        <asp:Label ID="Label_MSG1" runat="server" Text="Label"></asp:Label>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="--TSQL--
            SELECT * FROM [MyTable]
            WHERE ([Field2]=@Field2 OR @Field2=N'全部');">
            <SelectParameters>
                <asp:ControlParameter ControlID="DropDownList_Field2" Name="Field2" PropertyName="SelectedValue" />
            </SelectParameters>
        </asp:SqlDataSource>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="SN" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="SN" HeaderText="SN" InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                <asp:BoundField DataField="Field1" HeaderText="Field1" SortExpression="Field1" />
                <asp:BoundField DataField="Field2" HeaderText="Field2" SortExpression="Field2" />
            </Columns>
        </asp:GridView>

    </form>
</body>
</html>



Default.aspx.cs

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using Zaretto.ODS;  // NuGet ODSReaderWriter 1.0.10 使用

namespace WebApplication1
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        //【匯出(.ods)】
        #region === protected void Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e) ===
        protected void Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e)
        {
            // Import
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet

            // Export
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-create-a-spreadsheet-document-by-providing-a-file-name

            //Insert text into a cell in a spreadsheet document(Open XML SDK)
            //https://docs.microsoft.com/zh-tw/office/open-xml/how-to-insert-text-into-a-cell-in-a-spreadsheet

            string mainFileName = "匯出檔案名稱";

            // 若檔案名稱有中文字或特殊符號,Response.AddHeader() 輸出檔案名稱要編碼
            string outFileName = HttpUtility.UrlEncode(mainFileName, System.Text.Encoding.UTF8) + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";

            // XLWorkbook.SaveAs() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            // Response.TransmitFile() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            string dirFileName = @"D:\Production\TempImageFiles\" + mainFileName + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";
            try
            {
                Response.Clear();
                Response.Buffer = true;
                Response.Charset = "";

                #region === Export ODS ===

                // [EXCEL] Excel打開是亂碼?快速找回資料的最好方法!
                // http://blog.e-happy.com.tw/excel-excel%E6%89%93%E9%96%8B%E6%98%AF%E4%BA%82%E7%A2%BC%EF%BC%9F%E5%BF%AB%E9%80%9F%E6%89%BE%E5%9B%9E%E8%B3%87%E6%96%99%E7%9A%84%E6%9C%80%E5%A5%BD%E6%96%B9%E6%B3%95%EF%BC%81/

                // Excel開啟CSV時的中文編碼問題補遺
                //https://blog.darkthread.net/blog/csv-encoding-again/

                //Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                Response.ContentType = "application/vnd.oasis.opendocument.spreadsheet";    // ODF/.ods
                Response.AddHeader("content-disposition", "attachment;filename=" + outFileName);
                using (MemoryStream MyMemoryStream = new MemoryStream())
                {
                    StreamWriter odsFileStreamWriter = new StreamWriter(MyMemoryStream);
                    StreamReader odsFileStreamReader = new StreamReader(new MemoryStream());
                    string dataText = "";

                    DataSet ds = new DataSet("DS1");
                    //DataTable dt = new DataTable();
                    DataTable dt = ds.Tables.Add("工作表1");

                    string[] columnNameArray = {
"流水號"
,"欄位1"
,"欄位2"
        };
                    foreach (string columnName in columnNameArray)
                    {
                        DataColumn dataColumnName = new DataColumn
                        {
                            DataType = System.Type.GetType("System.String"),
                            ColumnName = columnName
                        };
                        dt.Columns.Add(dataColumnName);
                    }

                    DataRow dataColumnNameRow = dt.NewRow();
                    int ii = 0;
                    foreach (string columnName in columnNameArray)
                    {
                        dataColumnNameRow[ii] = columnName;
                        ii++;
                    }
                    dt.Rows.Add(dataColumnNameRow);

                    string queryString = SqlDataSource1.SelectCommand;
                    using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["MyDBConnectionString"].ConnectionString))
                    {
                        SqlCommand command = new SqlCommand(queryString, connection);
                        command.Parameters.Clear();
                        command.Parameters.AddWithValue("@Field2", DropDownList_Field2.SelectedValue);
                        connection.Open();

                        //Get All column 
                        //var columnNames = Enumerable.Range(0, reader.FieldCount)
                        //                        .Select(reader.GetName)
                        //                        .ToList();

                        ////Create headers
                        //sb.Append(string.Join(",", columnNames));

                        ////Append Line
                        //sb.AppendLine();

                        try
                        {
                            using (SqlDataReader reader = command.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    //Console.WriteLine(String.Format("{0}", reader[0]));
                                    DataRow datarow = dt.NewRow();
                                    for (int i = 0; i < reader.FieldCount; i++)
                                    {
                                        dataText = reader[i].ToString();
                                        // 換掉影響 CSV 顯示效果的字元
                                        dataText = dataText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(",", ",").Replace("'", "′").Replace(@"""", "”");
                                        //if (i > 0)
                                        //{
                                        //    datarow[i - 1] = dataText;
                                        //}
                                        datarow[i] = dataText;
                                        //if (i == 1)
                                        //{
                                        //    //if (csvContent=="")
                                        //    //    csvContent = dataText;
                                        //    //else
                                        //    //csvContent = csvContent + "\r\n" + dataText;
                                        //    csvContent.Append("\r\n" + dataText);

                                        //}
                                        //else
                                        //{
                                        //    //csvContent = csvContent + "," + dataText;
                                        //    csvContent.Append("," + dataText);
                                        //}
                                    }
                                    dt.Rows.Add(datarow);
                                }
                            }

                            //OdsReaderWriter odsFile = new OdsReaderWriter();  // OdsReaderWriter.cs 使用
                            ODSReaderWriter odsFile = new ODSReaderWriter();  // NuGet OdsReaderWriter 使用,注意大小寫不同
                            //odsFile.WriteOdsFile(ds, @"C:\TEMP\1.ods");
                            odsFile.WriteOdsFile(ds, dirFileName);

                            // Write the DataSet directly to the MemoryStream
                            // 格式有問題,WriteOdsFile 可能有對 ds (DataSet) 再處理,
                            // 所以此處直接以 Xml 寫入 MyMemoryStream 是不行的
                            //ds.WriteXml(MyMemoryStream);

                            Label_MSG1.ForeColor = System.Drawing.Color.Green;
                            string msg = DateTime.Now.ToString() + "匯出成功。";
                            Label_MSG1.Text = msg;
                            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                    Response.TransmitFile(dirFileName);
                    Response.End();

                    // Transmit the file directly without saving to server
                    //MyMemoryStream.Position = 0;
                    //MyMemoryStream.CopyTo(Response.OutputStream);
                }
                #endregion Export ODS
            }
            catch (Exception)
            {
                throw;
            }
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('匯出成功。');</script>");
        }
        #endregion
    }
}


實際測試可以成功。

(完)

相關

[研究]ASP.NET,WebForm,用 NuGet OdsReaderWriter 1.0.10 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-nuget-odsreaderwriter.html

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite








2024年3月29日 星期五

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods

2024-03-29

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

注意

  • OdsReaderWriter.cs 和 template.ods 從下面文章取得

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

下載得到 odsreadwrite.zip,包含 OdsReaderWriter.cs

  • OdsReaderWriter.cs 中

//ZipFile templateFile = this.GetZipFile(Assembly.GetExecutingAssembly().GetManifestResourceStream("OdsReadWrite.template.ods"));

改成

ZipFile templateFile = this.GetZipFile(File.OpenRead(HttpContext.Current.Server.MapPath("/template.ods")));


  • NuGet 要安裝 DotNetZip,要 using

using Ionic.Zip; // Ionic.Zip 被 DotNetZip 取代,NuGet 安裝 DotNetZip,但是 using 還是用舊名稱 Ionic.Zip

  • Web.Config 中暫時存放路徑,要手動建立好。


********************************************************************************

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="MyDBConnectionString" connectionString="Data Source=127.0.0.1;Initial Catalog=MyDB;User ID=sa;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="TempFolder" value="D:\Production\TempImageFiles\" />
  </appSettings>
</configuration>


Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication2.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:SqlDataSource ID="SqlDataSource_Field2" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="SELECT N'全部' AS [Field2], 0 AS Priority
            UNION
            SELECT DISTINCT [Field2], 1 AS Priority FROM [MyTable] ORDER BY Priority, [Field2]"></asp:SqlDataSource>
        <asp:DropDownList ID="DropDownList_Field2" runat="server"
            AutoPostBack="True" DataSourceID="SqlDataSource_Field2"
            DataTextField="Field2" DataValueField="Field2">
        </asp:DropDownList>
        <br />
        <asp:Button ID="Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip" runat="server" Text="匯出(.ods)"
            OnClick="Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click" /><br />
        <asp:Label ID="Label_MSG1" runat="server" Text="Label"></asp:Label>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="--TSQL--
            SELECT * FROM [MyTable]
            WHERE ([Field2]=@Field2 OR @Field2=N'全部');">
            <SelectParameters>
                <asp:ControlParameter ControlID="DropDownList_Field2" Name="Field2" PropertyName="SelectedValue" />
            </SelectParameters>
        </asp:SqlDataSource>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="SN" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="SN" HeaderText="SN" InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                <asp:BoundField DataField="Field1" HeaderText="Field1" SortExpression="Field1" />
                <asp:BoundField DataField="Field2" HeaderText="Field2" SortExpression="Field2" />
            </Columns>
        </asp:GridView>

    </form>
</body>
</html>



Default.aspx.cs

using OdsReadWrite; // 需要 OdsReaderWriter.cs 檔案
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;

namespace WebApplication2
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        //【匯出(.ods)】
        #region === protected void Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e) ===
        protected void Button_Export_ODS_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e)
        {
            // Import
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet

            // Export
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-create-a-spreadsheet-document-by-providing-a-file-name

            //Insert text into a cell in a spreadsheet document(Open XML SDK)
            //https://docs.microsoft.com/zh-tw/office/open-xml/how-to-insert-text-into-a-cell-in-a-spreadsheet

            string mainFileName = "匯出檔案名稱";

            // 若檔案名稱有中文字或特殊符號,Response.AddHeader() 輸出檔案名稱要編碼
            string outFileName = HttpUtility.UrlEncode(mainFileName, System.Text.Encoding.UTF8) + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";

            // XLWorkbook.SaveAs() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            // Response.TransmitFile() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            string dirFileName = @"D:\Production\TempImageFiles\" + mainFileName + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";
            try
            {
                Response.Clear();
                Response.Buffer = true;
                Response.Charset = "";

                #region === Export ODS ===

                // [EXCEL] Excel打開是亂碼?快速找回資料的最好方法!
                // http://blog.e-happy.com.tw/excel-excel%E6%89%93%E9%96%8B%E6%98%AF%E4%BA%82%E7%A2%BC%EF%BC%9F%E5%BF%AB%E9%80%9F%E6%89%BE%E5%9B%9E%E8%B3%87%E6%96%99%E7%9A%84%E6%9C%80%E5%A5%BD%E6%96%B9%E6%B3%95%EF%BC%81/

                // Excel開啟CSV時的中文編碼問題補遺
                //https://blog.darkthread.net/blog/csv-encoding-again/

                //Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                Response.ContentType = "application/vnd.oasis.opendocument.spreadsheet";    // ODF/.ods
                Response.AddHeader("content-disposition", "attachment;filename=" + outFileName);
                using (MemoryStream MyMemoryStream = new MemoryStream())
                {
                    StreamWriter odsFileStreamWriter = new StreamWriter(MyMemoryStream);
                    StreamReader odsFileStreamReader = new StreamReader(new MemoryStream());
                    string dataText = "";

                    DataSet ds = new DataSet("DS1");
                    //DataTable dt = new DataTable();
                    DataTable dt = ds.Tables.Add("工作表1");

                    string[] columnNameArray = {
"流水號"
,"欄位1"
,"欄位2"
        };
                    foreach (string columnName in columnNameArray)
                    {
                        DataColumn dataColumnName = new DataColumn
                        {
                            DataType = System.Type.GetType("System.String"),
                            ColumnName = columnName
                        };
                        dt.Columns.Add(dataColumnName);
                    }

                    DataRow dataColumnNameRow = dt.NewRow();
                    int ii = 0;
                    foreach (string columnName in columnNameArray)
                    {
                        dataColumnNameRow[ii] = columnName;
                        ii++;
                    }
                    dt.Rows.Add(dataColumnNameRow);

                    string queryString = SqlDataSource1.SelectCommand;
                    using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["MyDBConnectionString"].ConnectionString))
                    {
                        SqlCommand command = new SqlCommand(queryString, connection);
                        command.Parameters.Clear();
                        command.Parameters.AddWithValue("@Field2", DropDownList_Field2.SelectedValue);
                        connection.Open();

                        //Get All column 
                        //var columnNames = Enumerable.Range(0, reader.FieldCount)
                        //                        .Select(reader.GetName)
                        //                        .ToList();

                        ////Create headers
                        //sb.Append(string.Join(",", columnNames));

                        ////Append Line
                        //sb.AppendLine();

                        try
                        {
                            using (SqlDataReader reader = command.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    //Console.WriteLine(String.Format("{0}", reader[0]));
                                    DataRow datarow = dt.NewRow();
                                    for (int i = 0; i < reader.FieldCount; i++)
                                    {
                                        dataText = reader[i].ToString();
                                        // 換掉影響 CSV 顯示效果的字元
                                        dataText = dataText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(",", ",").Replace("'", "′").Replace(@"""", "”");
                                        //if (i > 0)
                                        //{
                                        //    datarow[i - 1] = dataText;
                                        //}
                                        datarow[i] = dataText;
                                        //if (i == 1)
                                        //{
                                        //    //if (csvContent=="")
                                        //    //    csvContent = dataText;
                                        //    //else
                                        //    //csvContent = csvContent + "\r\n" + dataText;
                                        //    csvContent.Append("\r\n" + dataText);

                                        //}
                                        //else
                                        //{
                                        //    //csvContent = csvContent + "," + dataText;
                                        //    csvContent.Append("," + dataText);
                                        //}
                                    }
                                    dt.Rows.Add(datarow);
                                }
                            }

                            OdsReaderWriter odsFile = new OdsReaderWriter();
                            //odsFile.WriteOdsFile(ds, @"C:\TEMP\1.ods");
                            odsFile.WriteOdsFile(ds, dirFileName);

                            Label_MSG1.ForeColor = System.Drawing.Color.Green;
                            string msg = DateTime.Now.ToString() + "匯出成功。";
                            Label_MSG1.Text = msg;
                            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                    Response.TransmitFile(dirFileName);
                    Response.End();
                }
                #endregion Export ODS
            }
            catch (Exception)
            {
                throw;
            }
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('匯出成功。');</script>");
        }
        #endregion

    }
}


實際測試可以成功匯入。



(完)

相關

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression

2024-03-29

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

[研究]ASP.NET, WebForm, 比較 DotNetZip 和 System.IO.Compression 差異 ?

https://shaurong.blogspot.com/2024/03/aspnet-webform-dotnetzip.html

********************************************************************************

https://github.com/haf/DotNetZip.Semverd

This repository has been archived by the owner on May 15, 2024. It is now read-only.

Please use System.IO.Compression! A fork of the DotNetZip project without signing with a solution that compiles cleanly. This project aims to follow semver to avoid versioning conflicts. DotNetZip is a FAST, FREE class library and toolset for manipulating zip files. Use VB, C# or any .NET language to easily create, extract, or update zip files.

DotNetZip淘汰了,請使用System.IO.Compression 套件。

********************************************************************************

2024-11-08 補,下面改寫出來程式不能用了,原因不明。

DotNetZip 套件對 .ods 這個 .zip 檔案的相容性操作,比 System.IO.Compression 套件要好。

********************************************************************************

OdsReaderWriter.cs 和 template.ods 從下面文章取得

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject

https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

下載得到 odsreadwrite.zip,包含 OdsReaderWriter.cs,其中 namespace OdsReadWrite

OdsReadWrite.cs

using System;
using System.Data;
using System.Globalization;
using System.IO;
using System.IO.Compression;    // Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
using System.Reflection;
using System.Web;
using System.Xml;
//using Ionic.Zip; // Ionic.Zip 被 DotNetZip 取代,NuGet 安裝 DotNetZip,但是 using 還是用舊名稱 Ionic.Zip

namespace OdsReadWrite
{
    internal sealed class OdsReaderWriter
    {
        // Namespaces. We need this to initialize XmlNamespaceManager so that we can search XmlDocument.
        private static string[,] namespaces = new string[,] 
        {
            {"table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0"},
            {"office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"},
            {"style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"},
            {"text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"},            
            {"draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"},
            {"fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"},
            {"dc", "http://purl.org/dc/elements/1.1/"},
            {"meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"},
            {"number", "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"},
            {"presentation", "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"},
            {"svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"},
            {"chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"},
            {"dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"},
            {"math", "http://www.w3.org/1998/Math/MathML"},
            {"form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0"},
            {"script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0"},
            {"ooo", "http://openoffice.org/2004/office"},
            {"ooow", "http://openoffice.org/2004/writer"},
            {"oooc", "http://openoffice.org/2004/calc"},
            {"dom", "http://www.w3.org/2001/xml-events"},
            {"xforms", "http://www.w3.org/2002/xforms"},
            {"xsd", "http://www.w3.org/2001/XMLSchema"},
            {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
            {"rpt", "http://openoffice.org/2005/report"},
            {"of", "urn:oasis:names:tc:opendocument:xmlns:of:1.2"},
            {"rdfa", "http://docs.oasis-open.org/opendocument/meta/rdfa#"},
            {"config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"}
        };

        // Read zip stream (.ods file is zip file).
        private ZipArchive GetZipArchive(Stream stream)
        {
            return new ZipArchive(stream, ZipArchiveMode.Read);
        }

        private ZipArchive GetZipArchive(string inputFilePath)
        {
            return ZipFile.OpenRead(inputFilePath);
        }

        private XmlDocument GetContentXmlFile(ZipArchive zipArchive)
        {
            ZipArchiveEntry contentZipEntry = zipArchive.GetEntry("content.xml");

            using (Stream contentStream = contentZipEntry.Open())
            {
                XmlDocument contentXml = new XmlDocument();
                contentXml.Load(contentStream);
                return contentXml;
            }
        }

        private XmlNamespaceManager InitializeXmlNamespaceManager(XmlDocument xmlDocument)
        {
            XmlNamespaceManager nmsManager = new XmlNamespaceManager(xmlDocument.NameTable);

            for (int i = 0; i < namespaces.GetLength(0); i++)
                nmsManager.AddNamespace(namespaces[i, 0], namespaces[i, 1]);

            return nmsManager;
        }

        public DataSet ReadOdsFile(string inputFilePath)
        {
            using (ZipArchive odsZipArchive = this.GetZipArchive(inputFilePath))
            {
                XmlDocument contentXml = this.GetContentXmlFile(odsZipArchive);
                XmlNamespaceManager nmsManager = this.InitializeXmlNamespaceManager(contentXml);

                DataSet odsFile = new DataSet(Path.GetFileName(inputFilePath));

                foreach (XmlNode tableNode in this.GetTableNodes(contentXml, nmsManager))
                    odsFile.Tables.Add(this.GetSheet(tableNode, nmsManager));

                return odsFile;
            }
        }

        private XmlNodeList GetTableNodes(XmlDocument contentXmlDocument, XmlNamespaceManager nmsManager)
        {
            return contentXmlDocument.SelectNodes("/office:document-content/office:body/office:spreadsheet/table:table", nmsManager);
        }

        private DataTable GetSheet(XmlNode tableNode, XmlNamespaceManager nmsManager)
        {
            DataTable sheet = new DataTable(tableNode.Attributes["table:name"].Value);

            XmlNodeList rowNodes = tableNode.SelectNodes("table:table-row", nmsManager);

            int rowIndex = 0;
            foreach (XmlNode rowNode in rowNodes)
                this.GetRow(rowNode, sheet, nmsManager, ref rowIndex);

            return sheet;
        }

        private void GetRow(XmlNode rowNode, DataTable sheet, XmlNamespaceManager nmsManager, ref int rowIndex)
        {
            XmlAttribute rowsRepeated = rowNode.Attributes["table:number-rows-repeated"];
            if (rowsRepeated == null || Convert.ToInt32(rowsRepeated.Value, CultureInfo.InvariantCulture) == 1)
            {
                while (sheet.Rows.Count < rowIndex)
                    sheet.Rows.Add(sheet.NewRow());

                DataRow row = sheet.NewRow();

                XmlNodeList cellNodes = rowNode.SelectNodes("table:table-cell", nmsManager);

                int cellIndex = 0;
                foreach (XmlNode cellNode in cellNodes)
                    this.GetCell(cellNode, row, nmsManager, ref cellIndex);

                sheet.Rows.Add(row);

                rowIndex++;
            }
            else
            {
                rowIndex += Convert.ToInt32(rowsRepeated.Value, CultureInfo.InvariantCulture);
            }

            // sheet must have at least one cell
            if (sheet.Rows.Count == 0)
            {
                sheet.Rows.Add(sheet.NewRow());
                sheet.Columns.Add();
            }
        }

        private void GetCell(XmlNode cellNode, DataRow row, XmlNamespaceManager nmsManager, ref int cellIndex)
        {
            XmlAttribute cellRepeated = cellNode.Attributes["table:number-columns-repeated"];

            if (cellRepeated == null)
            {
                DataTable sheet = row.Table;

                while (sheet.Columns.Count <= cellIndex)
                    sheet.Columns.Add();

                row[cellIndex] = this.ReadCellValue(cellNode);

                cellIndex++;
            }
            else
            {
                cellIndex += Convert.ToInt32(cellRepeated.Value, CultureInfo.InvariantCulture);
            }
        }

        private string ReadCellValue(XmlNode cell)
        {
            XmlAttribute cellVal = cell.Attributes["office:value"];

            if (cellVal == null)
                return String.IsNullOrEmpty(cell.InnerText) ? null : cell.InnerText;
            else
                return cellVal.Value;
        }

        /// <summary>
        /// Writes DataSet as .ods file.
        /// </summary>
        /// <param name="odsFile">DataSet that represent .ods file.</param>
        /// <param name="outputFilePath">The name of the file to save to.</param>

        public void WriteOdsFile(DataSet odsFile, string outputFilePath)
        {
            using (ZipArchive templateArchive = this.GetZipArchive(File.OpenRead(HttpContext.Current.Server.MapPath("/template.ods"))))
            {
                XmlDocument contentXml = this.GetContentXmlFile(templateArchive);
                XmlNamespaceManager nmsManager = this.InitializeXmlNamespaceManager(contentXml);

                XmlNode sheetsRootNode = this.GetSheetsRootNodeAndRemoveChildrens(contentXml, nmsManager);

                foreach (DataTable sheet in odsFile.Tables)
                    this.SaveSheet(sheet, sheetsRootNode);

                this.SaveContentXml(templateArchive, contentXml);

                templateArchive.Dispose();
            }
        }

        private XmlNode GetSheetsRootNodeAndRemoveChildrens(XmlDocument contentXml, XmlNamespaceManager nmsManager)
        {
            XmlNodeList tableNodes = this.GetTableNodes(contentXml, nmsManager);

            XmlNode sheetsRootNode = tableNodes.Item(0).ParentNode;
            // remove sheets from template file
            foreach (XmlNode tableNode in tableNodes)
                sheetsRootNode.RemoveChild(tableNode);

            return sheetsRootNode;
        }

        private void SaveSheet(DataTable sheet, XmlNode sheetsRootNode)
        {
            XmlDocument ownerDocument = sheetsRootNode.OwnerDocument;

            XmlNode sheetNode = ownerDocument.CreateElement("table:table", this.GetNamespaceUri("table"));

            XmlAttribute sheetName = ownerDocument.CreateAttribute("table:name", this.GetNamespaceUri("table"));
            sheetName.Value = sheet.TableName;
            sheetNode.Attributes.Append(sheetName);

            this.SaveColumnDefinition(sheet, sheetNode, ownerDocument);

            this.SaveRows(sheet, sheetNode, ownerDocument);

            sheetsRootNode.AppendChild(sheetNode);
        }

        private void SaveColumnDefinition(DataTable sheet, XmlNode sheetNode, XmlDocument ownerDocument)
        {
            XmlNode columnDefinition = ownerDocument.CreateElement("table:table-column", this.GetNamespaceUri("table"));

            XmlAttribute columnsCount = ownerDocument.CreateAttribute("table:number-columns-repeated", this.GetNamespaceUri("table"));
            columnsCount.Value = sheet.Columns.Count.ToString(CultureInfo.InvariantCulture);
            columnDefinition.Attributes.Append(columnsCount);

            sheetNode.AppendChild(columnDefinition);
        }

        private void SaveRows(DataTable sheet, XmlNode sheetNode, XmlDocument ownerDocument)
        {
            DataRowCollection rows = sheet.Rows;
            for (int i = 0; i < rows.Count; i++)
            {
                XmlNode rowNode = ownerDocument.CreateElement("table:table-row", this.GetNamespaceUri("table"));

                this.SaveCell(rows[i], rowNode, ownerDocument);

                sheetNode.AppendChild(rowNode);
            }
        }

        private void SaveCell(DataRow row, XmlNode rowNode, XmlDocument ownerDocument)
        {
            object[] cells = row.ItemArray;

            for (int i = 0; i < cells.Length; i++)
            {
                XmlElement cellNode = ownerDocument.CreateElement("table:table-cell", this.GetNamespaceUri("table"));

                if (row[i] != DBNull.Value)
                {
                    // We save values as text (string)
                    XmlAttribute valueType = ownerDocument.CreateAttribute("office:value-type", this.GetNamespaceUri("office"));
                    valueType.Value = "string";
                    cellNode.Attributes.Append(valueType);

                    XmlElement cellValue = ownerDocument.CreateElement("text:p", this.GetNamespaceUri("text"));
                    cellValue.InnerText = row[i].ToString();
                    cellNode.AppendChild(cellValue);
                }

                rowNode.AppendChild(cellNode);
            }
        }

        private void SaveContentXml(ZipArchive templateArchive, XmlDocument contentXml)
        {
            templateArchive.GetEntry("content.xml").Delete();

            using (MemoryStream memStream = new MemoryStream())
            {
                contentXml.Save(memStream);
                memStream.Seek(0, SeekOrigin.Begin);

                var entry = templateArchive.CreateEntry("content.xml");
                using (var entryStream = entry.Open())
                {
                    memStream.CopyTo(entryStream);
                }
            }
        }

        private string GetNamespaceUri(string prefix)
        {
            for (int i = 0; i < namespaces.GetLength(0); i++)
            {
                if (namespaces[i, 0] == prefix)
                    return namespaces[i, 1];
            }

            throw new InvalidOperationException("Can't find that namespace URI");
        }
    }
}



Default.aspx.cs


(下圖)匯入後

(完)

相關

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods

2024-03-29、2024-11-08

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

注意

  • OdsReaderWriter.cs 和 template.ods 從下面文章取得

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

  • OdsReaderWriter.cs 中

這行


//ZipFile templateFile = this.GetZipFile(Assembly.GetExecutingAssembly().GetManifestResourceStream("OdsReadWrite.template.ods"));

改成


ZipFile templateFile = this.GetZipFile(File.OpenRead(HttpContext.Current.Server.MapPath("/template.ods")));


  • NuGet 要安裝 DotNetZip,要 using

using Ionic.Zip; // Ionic.Zip 被 DotNetZip 取代,NuGet 安裝 DotNetZip,但是 using 還是用舊名稱 Ionic.Zip

  • Web.Config 中暫時存放路徑,要手動建立好。


********************************************************************************

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="MyDBConnectionString" connectionString="Data Source=127.0.0.1;Initial Catalog=MyDB;User ID=sa;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="TempFolder" value="D:\Production\TempImageFiles\" />
  </appSettings>
</configuration>


OdsCommon.cs

using Ionic.Zip; // Ionic.Zip 被 DotNetZip 取代,NuGet 安裝 DotNetZip,但是 using 還是用舊名稱 Ionic.Zip
using OdsReadWrite; // 需要 修改過的 OfdReadWrite.cs 檔案
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

namespace WebApplication2
{
    public class OdsCommon
    {
        //【匯出(.ods)】
        #region === public void ExportODS(string odsFilename, string sqlDataSourceSelectCommand) ===
        public static void ExportODS(string odsFilename,
            string[] columnNameArray,
            string sqlDataSourceSelectCommand,
            SqlParameter[] parameters)
        {
            // Import
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet

            // Export
            // https://docs.microsoft.com/en-us/office/open-xml/how-to-create-a-spreadsheet-document-by-providing-a-file-name

            //Insert text into a cell in a spreadsheet document(Open XML SDK)
            //https://docs.microsoft.com/zh-tw/office/open-xml/how-to-insert-text-into-a-cell-in-a-spreadsheet

            string mainFileName = odsFilename;

            // 若檔案名稱有中文字或特殊符號,Response.AddHeader() 輸出檔案名稱要編碼
            string outFileName = HttpUtility.UrlEncode(mainFileName, System.Text.Encoding.UTF8) + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";

            // XLWorkbook.SaveAs() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            // Response.TransmitFile() 輸出檔案名稱不要用 HttpUtility.UrlEncode 編碼
            string dirFileName = @"D:\Production\TempImageFiles\" + mainFileName + "-" +
                DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";
            try
            {
                System.Web.HttpContext.Current.Response.Clear();
                System.Web.HttpContext.Current.Response.Buffer = true;
                System.Web.HttpContext.Current.Response.Charset = "";

                #region === Export ODS ===

                // [EXCEL] Excel打開是亂碼?快速找回資料的最好方法!
                // http://blog.e-happy.com.tw/excel-excel%E6%89%93%E9%96%8B%E6%98%AF%E4%BA%82%E7%A2%BC%EF%BC%9F%E5%BF%AB%E9%80%9F%E6%89%BE%E5%9B%9E%E8%B3%87%E6%96%99%E7%9A%84%E6%9C%80%E5%A5%BD%E6%96%B9%E6%B3%95%EF%BC%81/

                // Excel開啟CSV時的中文編碼問題補遺
                //https://blog.darkthread.net/blog/csv-encoding-again/

                //Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                System.Web.HttpContext.Current.Response.ContentType = "application/vnd.oasis.opendocument.spreadsheet";    // ODF/.ods
                System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + outFileName);
                using (MemoryStream MyMemoryStream = new MemoryStream())
                {
                    StreamWriter odsFileStreamWriter = new StreamWriter(MyMemoryStream);
                    StreamReader odsFileStreamReader = new StreamReader(new MemoryStream());
                    string dataText = "";

                    DataSet ds = new DataSet("DS1");
                    //DataTable dt = new DataTable();
                    DataTable dt = ds.Tables.Add("工作表1");

                    //                    string[] columnNameArray = {
                    //"流水號"
                    //,"欄位1"
                    //,"欄位2"
                    //        };
                    foreach (string columnName in columnNameArray)
                    {
                        DataColumn dataColumnName = new DataColumn
                        {
                            DataType = System.Type.GetType("System.String"),
                            ColumnName = columnName
                        };
                        dt.Columns.Add(dataColumnName);
                    }

                    DataRow dataColumnNameRow = dt.NewRow();
                    int ii = 0;
                    foreach (string columnName in columnNameArray)
                    {
                        dataColumnNameRow[ii] = columnName;
                        ii++;
                    }
                    dt.Rows.Add(dataColumnNameRow);

                    //string queryString = SqlDataSource.SelectCommand;
                    string queryString = sqlDataSourceSelectCommand;
                    using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["MyDBConnectionString"].ConnectionString))
                    {
                        SqlCommand command = new SqlCommand(queryString, connection);
                        //command.Parameters.Clear();
                        //command.Parameters.AddWithValue("@cname", cname);
                        //command.Parameters.AddWithValue("@myemail", myemail);

                        if (parameters != null)
                        {
                            foreach (SqlParameter parameter in parameters)
                            {
                                command.Parameters.Add(parameter);
                            }
                        }

                        connection.Open();

                        //Get All column 
                        //var columnNames = Enumerable.Range(0, reader.FieldCount)
                        //                        .Select(reader.GetName)
                        //                        .ToList();

                        ////Create headers
                        //sb.Append(string.Join(",", columnNames));

                        ////Append Line
                        //sb.AppendLine();


                        try
                        {
                            using (SqlDataReader reader = command.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    //Console.WriteLine(String.Format("{0}", reader[0]));
                                    DataRow datarow = dt.NewRow();
                                    for (int i = 0; i < reader.FieldCount; i++)
                                    {
                                        dataText = reader[i].ToString();
                                        // 換掉影響 CSV 顯示效果的字元
                                        dataText = dataText.Replace("\r", "").Replace("\n", "").Replace("\t", "").Replace(",", ",").Replace("'", "′").Replace(@"""", "”");
                                        //if (i > 0)
                                        //{
                                        //    datarow[i - 1] = dataText;
                                        //}
                                        datarow[i] = dataText;
                                        //if (i == 1)
                                        //{
                                        //    //if (csvContent=="")
                                        //    //    csvContent = dataText;
                                        //    //else
                                        //    //csvContent = csvContent + "\r\n" + dataText;
                                        //    csvContent.Append("\r\n" + dataText);

                                        //}
                                        //else
                                        //{
                                        //    //csvContent = csvContent + "," + dataText;
                                        //    csvContent.Append("," + dataText);
                                        //}
                                    }
                                    dt.Rows.Add(datarow);
                                }
                            }

                            OdsReaderWriter odsFile = new OdsReaderWriter();
                            //odsFile.WriteOdsFile(ds, @"C:\TEMP\1.ods");
                            odsFile.WriteOdsFile(ds, dirFileName);

                            //Label_MSG1.ForeColor = System.Drawing.Color.Green;
                            //string msg = DateTime.Now.ToString() + "匯出成功。";
                            //Label_MSG1.Text = msg;
                            //Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('" + msg + "');</script>");
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                    System.Web.HttpContext.Current.Response.TransmitFile(dirFileName);
                    System.Web.HttpContext.Current.Response.End();
                }
                #endregion Export ODS
            }
            catch (Exception)
            {
                throw;
            }
            //Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('匯出成功。');</script>");
        }
        #endregion

        //建立參數
        #region === public static SqlParameter[] ConvertParameters(ParameterCollection parameters, Page page) ===
        public static SqlParameter[] ConvertParameters(ParameterCollection parameters, Page page)
        {
            SqlParameter[] sqlParameters = new SqlParameter[parameters.Count];
            for (int i = 0; i < parameters.Count; i++)
            {
                var parameter = parameters[i];
                if (parameter is ControlParameter)
                {
                    ControlParameter controlParameter = (ControlParameter)parameter;
                    var control = page.FindControl(controlParameter.ControlID);
                    // 確保找到控制元件
                    if (control != null)
                    {
                        string value = (control as ITextControl)?.Text ?? string.Empty;
                        sqlParameters[i] = new SqlParameter(parameter.Name, value);
                    }
                    else
                    {
                        // 找不到控制元件時,應該提供預設值,而不是引發 NullReferenceException
                        sqlParameters[i] = new SqlParameter(parameter.Name, DBNull.Value);
                    }
                }
                else
                {
                    // 如果參數不是控制參數,則使用 DBNull.Value
                    sqlParameters[i] = new SqlParameter(parameter.Name, DBNull.Value);
                }
            }
            return sqlParameters;
        }
        #endregion === public static SqlParameter[] ConvertParameters(ParameterCollection parameters, Page page) ===
    }
}

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication2.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:SqlDataSource ID="SqlDataSource_Field2" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="SELECT N'全部' AS [Field2], 0 AS Priority
            UNION
            SELECT DISTINCT [Field2], 1 AS Priority FROM [MyTable] ORDER BY Priority, [Field2]"></asp:SqlDataSource>
        <asp:DropDownList ID="DropDownList_Field2" runat="server"
            AutoPostBack="True" DataSourceID="SqlDataSource_Field2"
            DataTextField="Field2" DataValueField="Field2">
        </asp:DropDownList>
        <br />
        <asp:Button ID="Button_Export_ODS" runat="server" Text="匯出(.ods)"
            OnClick="Button_Export_ODS_Click" /><br />
        <asp:Label ID="Label_MSG1" runat="server" Text="Label"></asp:Label>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="--TSQL--
            SELECT * FROM [MyTable]
            WHERE ([Field2]=@Filed2 OR @Filed2=N'全部');">
            <SelectParameters>
                <asp:ControlParameter ControlID="DropDownList_Field2" Name="Filed2" PropertyName="SelectedValue" />
            </SelectParameters>
        </asp:SqlDataSource>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="SN" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="SN" HeaderText="SN" InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                <asp:BoundField DataField="Field1" HeaderText="Field1" SortExpression="Field1" />
                <asp:BoundField DataField="Field2" HeaderText="Field2" SortExpression="Field2" />
            </Columns>
        </asp:GridView>

    </form>
</body>
</html>


Default.aspx.cs

using System;
using System.Data.SqlClient;

namespace WebApplication2
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button_Export_ODS_Click(object sender, EventArgs e)
        {
            string[] columnNameArray = { "流水號", "欄位1", "欄位2" };
            SqlParameter[] sqlParameters = OdsCommon.ConvertParameters(SqlDataSource1.SelectParameters, this.Page);
            OdsCommon.ExportODS("匯出檔案名稱", columnNameArray, SqlDataSource1.SelectCommand, sqlParameters);
        }

    }
}


實際測試可以成功匯入。






********************************************************************************

2024-11-08補,測試正常。


********************************************************************************

(完)

相關

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods

2024-03-29

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

注意

  • OdsReaderWriter.cs 和 template.ods 從下面文章取得

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

  • OdsReaderWriter.cs 中

//ZipFile templateFile = this.GetZipFile(Assembly.GetExecutingAssembly().GetManifestResourceStream("OdsReadWrite.template.ods"));

改成

ZipFile templateFile = this.GetZipFile(File.OpenRead(HttpContext.Current.Server.MapPath("/template.ods")));


  • NuGet 要安裝 DotNetZip,要 using

using Ionic.Zip; // Ionic.Zip 被 DotNetZip 取代,NuGet 安裝 DotNetZip,但是 using 還是用舊名稱 Ionic.Zip

  • Web.Config 中暫時存放路徑,要手動建立好。


********************************************************************************

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<!--
  如需如何設定 ASP.NET 應用程式的詳細資訊,請前往
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <connectionStrings>
    <add name="MyDBConnectionString" connectionString="Data Source=127.0.0.1;Initial Catalog=MyDB;User ID=sa;Password=P@ssw0rd"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <appSettings>
    <add key="TempFolder" value="D:\Production\TempImageFiles\" />
  </appSettings>
</configuration>


Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:FileUpload ID="FileUpload1" runat="server" /><br />
        <%--<asp:Button ID="Button1" runat="server" Text="匯出(.ods)" OnClick="Button_Export_ODS_Click" />--%>
        <asp:Button ID="Button2" runat="server" Text="匯入(.ods)" OnClick="Button_Import_ods_by_OdsReaderWriter_DotNetZip_IonicZip_Click" /><br />
        <asp:Label ID="Label_MSG1" runat="server"></asp:Label><br />
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:MyDBConnectionString %>"
            SelectCommand="SELECT * FROM [MyTable]"></asp:SqlDataSource>
        <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
            AutoGenerateColumns="False" DataKeyNames="SN" DataSourceID="SqlDataSource1">
            <Columns>
                <asp:BoundField DataField="SN" HeaderText="SN" InsertVisible="False" ReadOnly="True" SortExpression="SN" />
                <asp:BoundField DataField="Field1" HeaderText="Field1" SortExpression="Field1" />
                <asp:BoundField DataField="Field2" HeaderText="Field2" SortExpression="Field2" />
            </Columns>
        </asp:GridView>
    </form>
</body>
</html>


Default.aspx.cs

using OdsReadWrite; // 需要 OdsReaderWriter.cs 檔案
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Web.Configuration;
using System.Web.UI;

namespace WebApplication1
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        //【匯入(.ods)】
        #region === protected void Button_Import_ods_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e) ===
        protected void Button_Import_ods_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e)
        {
            Label_MSG1.Text = "";
            int lineNo = 1;
            string queryString = "";
            int readSuccessLineCount = 0;
            
            if (FileUpload1.HasFile)
            {
                string fd = (string)ConfigurationManager.AppSettings["TempFolder"] + Path.DirectorySeparatorChar.ToString();
                //if (!System.IO.Directory.Exists(fd))
                //{
                //    System.IO.Directory.CreateDirectory(fd);
                //}
                string ext = System.IO.Path.GetExtension(FileUpload1.FileName).ToLower();
                if (!(ext == ".ods"))
                {
                    Label_MSG1.Text = "請上傳副檔名.ods檔案(Excel/OpenOffice/LibreOffice)";
                    ScriptManager.RegisterStartupScript(this, GetType(), "Popup1", "erroralert('" + "請上傳副檔名.ods檔案!" + "');", true);
                    return;
                }
                string fileName = fd + FileUpload1.FileName;
                FileUpload1.SaveAs(fileName);

                string mainFileName = Path.GetFileNameWithoutExtension(FileUpload1.FileName);
                string openFilename = fd + mainFileName + "-匯入結果" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-fff") + ".ods";
                FileUpload1.SaveAs(openFilename);

                OdsReaderWriter odsReaderWriter1 = new OdsReaderWriter();
                DataSet odsDataSet = odsReaderWriter1.ReadOdsFile(openFilename);

                string field1 = "";
                string field2 = "";

                try
                {
                    queryString = @"DELETE FROM [dbo].[MyTable]; ";

                    using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["MyDBConnectionString"].ConnectionString))
                    {
                        SqlCommand command = new SqlCommand(queryString, connection);
                        connection.Open();
                        command.ExecuteNonQuery();
                        lineNo++;
                    }

                    DataTable table = odsDataSet.Tables[0]; // 只抓第一個工作表,第二個工作表是說明

                    // 列數判斷法不正確,可能某些列看起來空白,實際有東西
                    for (int i = 1; i <= table.Rows.Count - 1; i++)
                    {
                        // 第0列(i=0)是標題,忽略不讀取,故 i=1 開始
                        // 第1欄位欄位的索引值是 0
                        field1 = table.Rows[i][0].ToString().Trim();
                        if (field1 != "")
                        {
                            field2 = table.Rows[i][1].ToString().Trim();
                            queryString = @"
INSERT INTO [dbo].[MyTable]
           ([Field1]
           ,[Field2])
     VALUES
           (@Field1
           ,@Field2)
";
                            using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["MyDBConnectionString"].ConnectionString))
                            {
                                SqlCommand command = new SqlCommand(queryString, connection);
                                command.Parameters.Clear();
                                command.Parameters.AddWithValue("@Field1", field1);
                                command.Parameters.AddWithValue("@Field2", field2);
                                connection.Open();
                                command.ExecuteNonQuery();
                                lineNo++;
                                readSuccessLineCount++;
                            }
                        }// if
                        else
                        {
                            //匯入完成,轉址離開
                            string id1 = "1";
                            string id2 = "2";
                            string url = String.Format("/List.aspx?ID1={0}&ID2={1}", id1, id2);
                            string msg = @"匯入.ods判定資料範圍" + (table.Rows.Count - 1) + "列" + (table.Columns.Count - 1) + "欄 (不表示其中每列or每欄位都有,可見or不可見)," +
                                "成功匯入" + readSuccessLineCount + "筆資料。第" + lineNo + "筆 (Excel 第" + (lineNo + 1) + "列) 第1欄必填「分類」為空的,中斷匯入。\\n" +
                                "若無法成功匯入想要的資料,請嘗試改用.xlsx匯入。\\n" +
                                "按【確定】轉往列表畫面。";
                            Label_MSG1.Text = "匯入成功。";
                            ClientScript.RegisterStartupScript(GetType(), "message", "<script>alert('" + msg + "');location.href='" + url + "';</script>");
                            return;
                        }
                    } // for
                }
                catch (Exception)
                {
                    throw;
                }
            } //if (FileUpload1.HasFile)
            else
            {
                Label_MSG1.Text = "請選擇.ods檔案";
                Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('請選擇.ods檔案。');</script>");
                return;
            }
            Label_MSG1.Text = "匯入成功。";
            GridView1.DataBind();
        }
        #endregion === protected void Button_Import_ods_by_OdsReaderWriter_DotNetZip_IonicZip_Click(object sender, EventArgs e) ===
    }
}


實際測試可以成功匯入。

(下圖)匯入前


(下圖)選擇檔案,匯入後


(完)

相關

[研究]ASP.NET,WebForm, 把 OdsReadWrite.cs 從 Ionic.Zip 或 DotNetZip 改成用 System.IO.Compression
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreadwritecs-ioniczip.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 共用匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_79.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯出 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_23.html

[研究]ASP.NET,WebForm,用 OdsReaderWriter + DotNetZip (Ionic.Zip) 1.16.0 匯入 .ods
https://shaurong.blogspot.com/2024/03/aspnetwebform-odsreaderwriter-dotnetzip_93.html

How to Read and Write ODF/ODS Files (OpenDocument Spreadsheets) - CodeProject
https://www.codeproject.com/Articles/38425/How-to-Read-and-Write-ODF-ODS-Files-OpenDocument-2

[研究][ASP.NET]讀取、匯出、寫入、匯入 Excel .xlsx .xls ODF .ods
https://shaurong.blogspot.com/2020/04/caspnetwebform-excel-xlsx-xls-odf-ods.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 (Ionic.Zip) 匯出寫入 .ods
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150_9.html

[研究][ASP.NET]使用 OdsReaderWriter + DotNetZip 1.15.0 讀取匯入 .ods 到資料庫
https://shaurong.blogspot.com/2021/02/aspnet-odsreaderwriter-dotnetzip-1150.html

[研究][C#]用OdsReaderWrite匯出(寫入)、匯入(讀取) ODF/.ods 檔案 (使用 Ionic.Zip、DotNetZip)
https://shaurong.blogspot.com/2020/09/caspnetwebform-ioniczip-odfods.html

[研究] [C#] 用OdsReadWrite讀取 LibreOffice、OpenOffice 的試算表(Calc) 檔案 (.ods)(使用 .NET 4.5 的 ZipFile)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods-net-45.html

[研究] [C#] 用OdsReaderWrite讀取 LibreOffice 5.1.6 的試算表(Calc) 檔案 (.ods)(使用 DotNetZip)
https://shaurong.blogspot.com/2016/12/c-libreoffice-516-calc-ods.html

NuGet Gallery | OdsReaderWriter 1.0.10
https://www.nuget.org/packages/OdsReaderWriter

sortings/OdsReadWrite at master · Luviz/sortings · GitHub
https://github.com/Luviz/sortings/tree/master/OdsReadWrite