Excel保存文档时如何在编辑后保留OpenXml单元格属性?

我想导出一个excel文件与数据,以便我的用户可以:

  • 下载一个Excel文件(从我的程序导出)
  • 编辑文件中的数据
  • 保存
  • 上传Excel文件(将其重新导入到我的程序中)

基本上我会给他们一个离线文件的经验,如果他们没有互联网访问权限,他们可以编辑(因为我们是一个networking应用程序)

使用OpenXml SDK创buildExcel文件时,我使用OpenXmlElement.SetAttribute方法将属性添加到工作表的列,行和单元格中。 我添加的属性用于重新导入时,我可以将编辑的数据与应该存储的位置相匹配。

我输出的属性是:

  • 数据库ID的
  • 原始值(导出时的数据库值,以便于导入同步)
  • 导出数据的上次修改date

导出例程如下所示:

var cell = new Cell { CellReference = string.Format("{0}{1}", Column.Reference, Row.Index), DataType = this.CellDataType }; foreach (var keyValuePair in this.AttributeDictionary) { cell.SetAttribute(new OpenXmlAttribute { LocalName = keyValuePair.Key, Value = keyValuePair.Value.ToString() }); } 

这个出口工作正常。 在OpenXml生产力工具中检查导出的文件时,可以看到正确添加的属性。 在Excel中编辑后保存文件时,不保留属性。 有没有办法告诉Excel保存的属性,或者是否有另一个程序,这里是最好的用来保存我需要的数据,以便轻松重新input数据?

边问题:

如果Excel不保留它们,属性是什么?

我不认为你可以强制Excel往返未知的属性,但你可以添加扩展元素使用ExtensionListsExtensions 。 Excel将对这些元素进行往返处理,并按照您的需求进行devise(据我所知)来存储应用程序特定的数据。

似乎没有太多的文档可以find,但ECMA-376规范的第3部分提到了扩展。

下面的代码将在单元格A1中创build一个具有值的表单,并将一个具有一个Extension作为该单元格的子表单创build:

 public static void CreateSpreadsheetWorkbook(string filepath) { if (File.Exists(filepath)) File.Delete(filepath); using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)) { // Add a WorkbookPart to the document. WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); workbookpart.Workbook = new Workbook(); // Add a WorksheetPart to the WorkbookPart. WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); SheetData sheetData = new SheetData(); worksheetPart.Worksheet = new Worksheet(sheetData); // Add Sheets to the Workbook. Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets()); // Append a new worksheet and associate it with the workbook. Sheet sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart. GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet1" }; sheets.Append(sheet); Row row = new Row() { RowIndex = 1U }; Cell cell = new Cell() { CellReference = "A1", CellValue = new CellValue("A Test"), DataType = CellValues.String }; ExtensionList extensions = new ExtensionList(); Extension extension = new Extension() { Uri = "Testing1234" }; extensions.AppendChild(extension); extension.AddNamespaceDeclaration("ns", "http://tempuri/someUrl"); cell.AppendChild(extensions); row.Append(cell); sheetData.Append(row); workbookpart.Workbook.Save(); // Close the document. spreadsheetDocument.Close(); } } 

以下内容将再次读取该值,即使文件已通过Excel进行了四舍五入。

 public static void ReadSheet(string filename, string sheetName) { using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filename, false)) { WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart; //get the correct sheet Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).First(); if (sheet != null) { WorksheetPart worksheetPart = workbookPart.GetPartById(sheet.Id) as WorksheetPart; foreach (Cell cell in worksheetPart.Worksheet.Descendants<Cell>()) { ExtensionList extensions = cell.GetFirstChild<ExtensionList>(); if (extensions != null) { Extension extension = extensions.GetFirstChild<Extension>(); if (extension != null) { Console.WriteLine("Cell {0} has value {1}", cell.CellReference, extension.Uri); } } } } } } 

其输出是

单元格A1的值为Testing1234

至于你方的问题:

如果Excel不保留它们,属性是什么?

我不太确定 – 我唯一使用OpenXmlAttribute类的时候是使用SAX方法编写文档的。 在这种情况下,你需要明确地写出属性和元素。 例如:

 List<OpenXmlAttribute> oxa = new List<OpenXmlAttribute>(); //cell reference attribute oxa.Add(new OpenXmlAttribute("r", "", "A1")); //cell type attribute oxa.Add(new OpenXmlAttribute("t", "", "str")); //write the start element of a cell with the above attributes oxw.WriteStartElement(new Cell(), oxa); //write a value to the cell oxw.WriteElement(new CellValue("Test")); //write the end element oxw.WriteEndElement(); 

我的答案在这里有一个使用SAX方法的完整例子。