我正在使用OpenXML以便将一些翻译数据导出到Excel电子表格,然后将同一电子表格导入到我的程序中。
现在,即使我直接导出和导入,此方法也可以很好地工作,但是,如果我在excel中打开op电子表格并对其进行编辑或保存,则程序无法读取数据,就好像它已损坏一样。但是,如果我再次打开它,Excel认为它很好,因此该文件实际上并没有损坏。
using (SpreadsheetDocument document = SpreadsheetDocument.Create(saveLocation, SpreadsheetDocumentType.Workbook))
...
//Add a WorkbookPart to the document
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
//Add a WorksheetPart to the WorkbookPart
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
//Add style
WorkbookStylesPart stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = GenerateStylesheet();
stylePart.Stylesheet.Save();
...
SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
//Append some rows
...
worksheetPart.Worksheet.Save();
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileStream, false))
{
WorkbookPart workbookPart = document.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
var headerRow = sheetData.Elements<Row>().FirstOrDefault();
...
//All data here are numbers
因此,最初我认为可能是由excel创建的更多工作表,并且我以为.First()会为我提供正确的工作表,但我完全错了,但是在调试时查看该对象表明数据在某种程度上是正确的。因此,显然这里有些问题,所以我决定查看.xlsx文件的存档内容。
我不知道为什么会这样,如果它是某种预期的行为。我发现OpenXML充满了奇怪的设计选择,但是在经历了迷宫般的迷路之后,这才是真正阻止我前进的第一件事。
我正在macOS上的Netcore 2.0上构建,显然Excel也正在macOS上运行。
如果有人可以帮助我解决这个问题,我将非常高兴。
答案 0 :(得分:0)
有两种方法将字符串存储在Excel文件中;就像创建时一样使用内联字符串,或者如注释中指出的那样,使用称为SharedStringTable的单独XML文件。 Excel碰巧使用了后一种方法,因此直接在每个包含字符串的单元格中插入它们,而是在SharedStringTable中包含一个条目的索引。
幸运的是,您可以像使用文档的任何其他部分一样使用OpenXML读取SharedStringTable。例如:
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileStream, false))
{
WorkbookPart workbookPart = document.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
SharedStringTablePart stringTable = workbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
var headerRow = sheetData.Elements<Row>().FirstOrDefault();
foreach (Cell c in headerRow.Elements<Cell>())
{
string cellText;
if (c.DataType == CellValues.SharedString)
{
//the value will be a number which is an index into the shared strings table
int index = int.Parse(c.CellValue.InnerText);
cellText = stringTable.SharedStringTable.ElementAt(index).InnerText;
}
else
{
//just take the value from the cell (note this won't work for some types e.g. dates)
cellText = c.CellValue.InnerText;
}
Console.WriteLine(cellText);
}
}
}
对于大文件,您可能需要考虑按照本问题和答案中的讨论来缓存共享字符串。