OpenXML 如何添加指向另一个的超链接 sheet
OpenXML How to add hyperlink that points to another sheet
我正在寻找如何向单元格添加超链接的示例。
似乎不像添加文本那么容易。
我得到了生成正确 XML 但在 excel 中没有链接的和平代码
private SheetData PopulateSheetWithData(SheetData sheetData, IList<Event> events, SpreadsheetDocument document)
{
int errorIndex = 0;
foreach (var @event in events)
{
errorIndex++;
Hyperlinks hyperlinks = new Hyperlinks();
Hyperlink hyperlink = new Hyperlink()
{
Location = "UniqueError_" + errorIndex + "!A1",
Display = @event.LOG_CORR_KEY,
Reference = "A"+(errorIndex+1),
Id = "UniqueError_" + errorIndex
};
hyperlinks.AppendChild(hyperlink);
sheetData.AppendChild(hyperlinks);
}
return sheetData;
}
我做错了什么吗?
我找到了 this 篇关于如何添加超链接的文章,但它看起来太复杂了。对这个问题有帮助吗?
因此,在 table 上苦苦思索了一段时间后,我决定专注于 OpenXML Excell 调查,我成功了!
我找到了一个关于如何插入超链接到 excel 文件的解决方案,甚至更多,现在我的程序可以创建多个 sheets,这取决于我的数据对象。
我很兴奋,我想和大家分享我的成就。
首先,您需要创建 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 为何以及如何依赖 Excell 中的超链接,但我确信如果没有此超链接,Excell 文件将无法正常工作,生成的文件也会损坏。
下一步,我们需要为 WorkBookPart 创建一个 workbook 也为 workbook 我们需要创建一个 Sheets 来容纳所有 sheet。对于每个 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 添加到总数中?因为首先,由于某种原因,sheet 的 RelationshipId ( Id ) 不能为 0,所以我需要从 1 开始,第二,我的第一页excel是导航页所以我也跳过了。
为文档创建 WorkBookPart 后,我将开始为每个 Sheet[=53= 创建 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 - 随着我的 objects 一个接一个地进行,我可以确保 Indexer 与 rId 相同数字,也等于第一列行号。
我还制作了一些助手 ConstructHeader,它在第一行构造 headers,它接受 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,
};
}
总结:
此代码将创建一个 Excell 文档,其中第一个 Sheet 作为导航,其他 sheet 具有来自 DataObject 的填充数据。我希望这会对某人有所帮助。
另外,如果您有任何意见或反馈 - 请分享我想听听。
这对我有用,并将“test.xlsx”的 Sheet1 中的 C1 链接到 Sheet2 中的 A10
static void AddHyperlink()
{
var filePath = "test.xlsx";
// C1 in Sheet1
var sheetName1 = "Sheet1";
var column = "C";
var row = 1;
// Link to A10 in Sheet2
var pathToOtherFile = filePath;
var sheetName2 = "Sheet2";
var cellRef = "A10";
using (var document = SpreadsheetDocument.Open(filePath, true))
{
WorkbookPart wbPart = document.WorkbookPart;
var sheets = document.WorkbookPart.Workbook.Sheets.Cast<Sheet>().ToList();
var sheet = sheets.Where(x => x.Name == sheetName1).FirstOrDefault();
string relationshipId = sheets.First().Id.Value;
//get the worksheetpart by Id
WorksheetPart worksheetPart = (WorksheetPart)wbPart.GetPartById(relationshipId);
var worksheet = worksheetPart.Worksheet;
Cell cell = GetCell(worksheet, column, row);
var s = cell.LastChild;
var cell1 = cell;
CellFormula cellFormula1 = new CellFormula() { Space = SpaceProcessingModeValues.Preserve };
cellFormula1.Text = $"HYPERLINK(\"[{pathToOtherFile}]{sheetName2}!{cellRef}\", \"Radio Clash\")";
cell1.CellFormula = cellFormula1;
}
}
private static Cell GetCell(Worksheet worksheet, string columnName, int rowIndex)
{
Row row = GetRow(worksheet, rowIndex);
if (row == null)
return null;
return row.Elements<Cell>().Where(c => string.Compare
(c.CellReference.Value, columnName +
rowIndex, true) == 0).First();
}
// Given a worksheet and a row index, return the row.
private static Row GetRow(Worksheet worksheet, int rowIndex)
{
return worksheet.GetFirstChild<SheetData>().
Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
}
如果你想使用自引用(不引用另一个文件),你可以使用:
cellFormula1.Text = $"=HYPERLINK(\"[\" & MID(CELL(\"filename\"),SEARCH(\"[\",CELL(\"filename\"))+1, SEARCH(\"]\",CELL(\"filename\"))-SEARCH(\"[\",CELL(\"filename\"))-1) &\"]{sheetName2}!{cellRef}\", \"Radio Clash\")";
而不是:
cellFormula1.Text = $"HYPERLINK(\"[{pathToOtherFile}]{sheetName2}!{cellRef}\", \"Radio Clash\")";
我正在寻找如何向单元格添加超链接的示例。 似乎不像添加文本那么容易。
我得到了生成正确 XML 但在 excel 中没有链接的和平代码
private SheetData PopulateSheetWithData(SheetData sheetData, IList<Event> events, SpreadsheetDocument document)
{
int errorIndex = 0;
foreach (var @event in events)
{
errorIndex++;
Hyperlinks hyperlinks = new Hyperlinks();
Hyperlink hyperlink = new Hyperlink()
{
Location = "UniqueError_" + errorIndex + "!A1",
Display = @event.LOG_CORR_KEY,
Reference = "A"+(errorIndex+1),
Id = "UniqueError_" + errorIndex
};
hyperlinks.AppendChild(hyperlink);
sheetData.AppendChild(hyperlinks);
}
return sheetData;
}
我做错了什么吗? 我找到了 this 篇关于如何添加超链接的文章,但它看起来太复杂了。对这个问题有帮助吗?
因此,在 table 上苦苦思索了一段时间后,我决定专注于 OpenXML Excell 调查,我成功了!
我找到了一个关于如何插入超链接到 excel 文件的解决方案,甚至更多,现在我的程序可以创建多个 sheets,这取决于我的数据对象。 我很兴奋,我想和大家分享我的成就。
首先,您需要创建 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 为何以及如何依赖 Excell 中的超链接,但我确信如果没有此超链接,Excell 文件将无法正常工作,生成的文件也会损坏。
下一步,我们需要为 WorkBookPart 创建一个 workbook 也为 workbook 我们需要创建一个 Sheets 来容纳所有 sheet。对于每个 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 添加到总数中?因为首先,由于某种原因,sheet 的 RelationshipId ( Id ) 不能为 0,所以我需要从 1 开始,第二,我的第一页excel是导航页所以我也跳过了。
为文档创建 WorkBookPart 后,我将开始为每个 Sheet[=53= 创建 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 - 随着我的 objects 一个接一个地进行,我可以确保 Indexer 与 rId 相同数字,也等于第一列行号。
我还制作了一些助手 ConstructHeader,它在第一行构造 headers,它接受 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,
};
}
总结: 此代码将创建一个 Excell 文档,其中第一个 Sheet 作为导航,其他 sheet 具有来自 DataObject 的填充数据。我希望这会对某人有所帮助。 另外,如果您有任何意见或反馈 - 请分享我想听听。
这对我有用,并将“test.xlsx”的 Sheet1 中的 C1 链接到 Sheet2 中的 A10
static void AddHyperlink()
{
var filePath = "test.xlsx";
// C1 in Sheet1
var sheetName1 = "Sheet1";
var column = "C";
var row = 1;
// Link to A10 in Sheet2
var pathToOtherFile = filePath;
var sheetName2 = "Sheet2";
var cellRef = "A10";
using (var document = SpreadsheetDocument.Open(filePath, true))
{
WorkbookPart wbPart = document.WorkbookPart;
var sheets = document.WorkbookPart.Workbook.Sheets.Cast<Sheet>().ToList();
var sheet = sheets.Where(x => x.Name == sheetName1).FirstOrDefault();
string relationshipId = sheets.First().Id.Value;
//get the worksheetpart by Id
WorksheetPart worksheetPart = (WorksheetPart)wbPart.GetPartById(relationshipId);
var worksheet = worksheetPart.Worksheet;
Cell cell = GetCell(worksheet, column, row);
var s = cell.LastChild;
var cell1 = cell;
CellFormula cellFormula1 = new CellFormula() { Space = SpaceProcessingModeValues.Preserve };
cellFormula1.Text = $"HYPERLINK(\"[{pathToOtherFile}]{sheetName2}!{cellRef}\", \"Radio Clash\")";
cell1.CellFormula = cellFormula1;
}
}
private static Cell GetCell(Worksheet worksheet, string columnName, int rowIndex)
{
Row row = GetRow(worksheet, rowIndex);
if (row == null)
return null;
return row.Elements<Cell>().Where(c => string.Compare
(c.CellReference.Value, columnName +
rowIndex, true) == 0).First();
}
// Given a worksheet and a row index, return the row.
private static Row GetRow(Worksheet worksheet, int rowIndex)
{
return worksheet.GetFirstChild<SheetData>().
Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
}
如果你想使用自引用(不引用另一个文件),你可以使用:
cellFormula1.Text = $"=HYPERLINK(\"[\" & MID(CELL(\"filename\"),SEARCH(\"[\",CELL(\"filename\"))+1, SEARCH(\"]\",CELL(\"filename\"))-SEARCH(\"[\",CELL(\"filename\"))-1) &\"]{sheetName2}!{cellRef}\", \"Radio Clash\")";
而不是:
cellFormula1.Text = $"HYPERLINK(\"[{pathToOtherFile}]{sheetName2}!{cellRef}\", \"Radio Clash\")";