所以经过一段时间的努力,我决定专注于我的 OpenXML Excell 调查,我成功了!
我找到了一个关于如何将超链接插入到 excel 文件的解决方案,甚至更多,现在我的程序可以创建多个工作表,这些工作表的数量取决于我的 dataObject。
我很兴奋,我想与大家分享我的成就。
首先,您需要创建 SpreadSheetDocument,因此我创建了一个方法 CreatePackage 并作为参数传递 filePath 以及我的 DataObject
public void CreatePackage(string filePath, List<DataObject> data)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Create(filePath, SpreadsheetDocumentType.Workbook)
)
{
CreateParts(document, data);
}
}
CreateParts 方法接受 SpreadsheetDocument 和 DataObject
private void CreateParts(SpreadsheetDocument document, List<DataObject> data)
{
ExtendedFilePropertiesPart extendedFilePropertiesPart = document.AddNewPart<ExtendedFilePropertiesPart>();
extendedFilePropertiesPart.Properties = new Properties();
WorkbookPart workbookPart = document.AddWorkbookPart();
//Create new sheet for every Unique error
GenerateWorkbookPart(workbookPart,data.Count);
//generates new SheetPart for every sheet
GenerateWorkSheetsParts(workbookPart,data);
}
我无法找到 ExtendedFilePropertiesPart 依赖 Excel 中 HyperLink 的原因和方式,但我确信没有此超链接将无法工作,即使 Excell 文件生成时也会损坏。
接下来,我们需要为 WorkBookPart 创建一个 workbook 也为 workbook 我们需要创建一个 Sheets它将容纳所有 工作表。对于每个 sheet,我们还需要创建 WorkSheetPart,但对此,我稍后会回来。现在:
private void GenerateWorkbookPart(WorkbookPart workbookPart, int dataCount)
{
Workbook workbook = new Workbook();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
for (int i = 1; i < dataCount+2; i++)
{
var relId = "rId" + i;
if (i == 1)
{
sheet = new Sheet()
{
Name = "Main",
SheetId = (uint) i,
Id = relId
};
}
else
{
sheet = new Sheet()
{
Name = "Unique" + (i-1),
SheetId = (uint)i,
Id = relId
};
}
sheets.AppendChild(sheet);
}
workbook.AppendChild(sheets);
workbookPart.Workbook = workbook;
}
为什么我要在总数中加上 +2?因为首先,由于某种原因,工作表的RelationshipId(Id)不能为0,所以我需要从1开始,第二,我的excel中的第一页是导航页所以我也跳过它。
为我的文档创建 WorkBookPart 后,我将开始为每个 Sheet 创建 WorkSheetPart 并用数据填充它。
private void GenerateWorkSheetsParts(WorkbookPart workbookPart, List<DataObject> data)
{
for (int i = 1; i < data.Count+2; i++)
{
var relId = "rId" + i;
if (i == 1)
{
WorksheetPart workSheetPart = workbookPart.AddNewPart<WorksheetPart>(relId);
GenerateWorkSheetPartContent(workSheetPart, i, data);
}
else
{
WorksheetPart workSheetPart = workbookPart.AddNewPart<WorksheetPart>(relId);
GenerateWorkSheetPartContent(workSheetPart, i, data[i-2].NestedObject);
}
}
}
private void GenerateWorkSheetPartContent(WorksheetPart worksheetPart,int indexer, List<NestedObject> data)
{
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
Hyperlinks hyperlinks = new Hyperlinks();
if (indexer == 1)
{
sheetData.AppendChild(ConstructHeader("Unique errors", "Count"));
foreach (var @event in data)
{
indexer++;
Row row = new Row();
row.Append(ConstructCell(@event.ErrorMessage, "A" + indexer, CellValues.String), ConstructCell(@event.ListOfErrorsObject.Count.ToString(), CellValues.Number));
sheetData.AppendChild(row);
Hyperlink hyperlink = new Hyperlink()
{
Reference = "A" + indexer,
Location = "Unique" + (indexer - 1)+"!A1",
Display = "Unique" + indexer
};
hyperlinks.AppendChild(hyperlink);
}
worksheet.Append(sheetData, hyperlinks);
worksheetPart.Worksheet = worksheet;
}
else
{
worksheet.AppendChild(sheetData);
worksheetPart.Worksheet = worksheet;
}
}
Indexer - 当我的对象一个接一个地移动时,我可以确保 Indexer 与 rId 编号相同,并且也等于第一列的行号。 p>
我还做了一些帮助器ConstructHeader,它在第一行构造标题,它需要String和ConstructCell的参数,这有助于更快地构造我可以附加到的单元格排。它还有一个重载,用于构造一个应该带有超链接的单元格。
private Row ConstructHeader(params string[] headers)
{
Row row = new Row();
foreach (var header in headers)
{
row.AppendChild(ConstructCell(header, CellValues.String));
}
return row;
}
private Cell ConstructCell(string value, CellValues dataType)
{
return new Cell()
{
CellValue = new CellValue(value),
DataType = new EnumValue<CellValues>(dataType),
};
}
private Cell ConstructCell(string value, string cellReference, CellValues dataType)
{
return new Cell()
{
CellReference = cellReference,
CellValue = new CellValue(value),
DataType = dataType,
};
}
总结:
此代码将创建一个 Excel 文档,其中第一个工作表作为导航,其他工作表包含来自 DataObject 的填充数据。我希望这会对某人有所帮助。
另外,如果您有任何 cmets 或反馈 - 请分享我想听听。