[研究]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
沒有留言:
張貼留言