如何使用OpenXML从Excel表格中检索标签名称
我有一个电子表格文档,其中有182列。我需要将电子表格数据放入一个数据表中,但是我需要找出每个标签添加数据,标签名称是什么,并将标签名称添加到数据表中的一列。如何使用OpenXML从Excel表格中检索标签名称
这是我如何设置数据表。
然后,我在工作簿中循环并深入到sheetData
对象并遍历每行和每列,获取单元格数据。
DataTable dt = new DataTable();
for (int i = 0; i <= col.GetUpperBound(0); i++)
{
try
{
dt.Columns.Add(new DataColumn(col[i].ToString(), typeof(string)));
}
catch (Exception e)
{
MessageBox.Show("Uploader Error" + e.ToString());
return null;
}
}
dt.Columns.Add(new DataColumn("SheetName", typeof(string)));
但是,在我用于数据表的字符串数组的末尾,我需要添加标签名称。我如何在Open XML的工作表中循环查找标签名称?
这是到目前为止我的代码:
using (SpreadsheetDocument spreadSheetDocument =
SpreadsheetDocument.Open(Destination, false))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
Workbook workbook = spreadSheetDocument.WorkbookPart.Workbook;
Sheets sheets =
spreadSheetDocument
.WorkbookPart
.Workbook
.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
OpenXmlElementList list = sheets.ChildElements;
foreach (WorksheetPart worksheetpart in workbook.WorkbookPart.WorksheetParts)
{
Worksheet worksheet = worksheetpart.Worksheet;
foreach (SheetData sheetData in worksheet.Elements<SheetData>())
{
foreach (Row row in sheetData.Elements())
{
string[] thisarr = new string[183];
int index = 0;
foreach (Cell cell in row.Elements())
{
thisarr[(index)] = GetCellValue(spreadSheetDocument, cell);
index++;
}
thisarr[182] = ""; //need to add tabname here
if (thisarr[0].ToString() != "")
{
dt.Rows.Add(thisarr);
}
}
}
}
}
return dt;
刚一说明:我在
OpenXmlElementList list = sheets.ChildElements;
但是我注意到,我没有以前得到“名单”的InnerXML属性选项卡名称在电子表格中循环时,它不会以正确的顺序获得标签名称。
的片材的名称被存储在WorkbookPart
在具有元件Sheet
,其对应于在Excel文件每个工作表的儿童Sheets
元件。您所要做的就是从Sheets
元素中获取正确的索引,这将是您循环中的Sheet
。我在下面添加了一段代码来做你想做的事情。
int sheetIndex = 0;
foreach (WorksheetPart worksheetpart in workbook.WorkbookPart.WorksheetParts)
{
Worksheet worksheet = worksheetpart.Worksheet;
// Grab the sheet name each time through your loop
string sheetName = workbookPart.Workbook.Descendants<Sheet>().ElementAt(sheetIndex).Name;
foreach (SheetData sheetData in worksheet.Elements<SheetData>())
{
...
}
sheetIndex++;
}
这是一个很好的解决方案。谢谢阿穆拉! – Kwalke001
根据我的经验,使用您的代码片段,sheetName以正确的顺序(如它们在文件中)读取表名,但sheetData不按照它们在Excel文件中的顺序读取。结果代码导致所有工作表的混合名称。 – Skull
似乎问题来自“excel_file.xlsx \ xl \ _rels \ workbook.xml.rels”文件,该文件具有电子表格名称和对以某种随机顺序存储的电子表格内容的引用。如果您手动将它们从1重新排序到N(Id =“rId1”,Id =“rId2”,...,Id =“rIdN”),电子表格名称将在读取文件后与其内容对齐。不知道如何在代码中处理这个问题。 – Skull
worksheet.GetAttribute("name","").Value
Using spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Open("D:\Libro1.xlsx", True)
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
workbookPart.Workbook.Descendants(Of Sheet)()
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.Last
Dim text As String
For Each Sheet As Sheet In spreadsheetDocument.WorkbookPart.Workbook.Sheets
Dim sName As String = Sheet.Name
Dim sID As String = Sheet.Id
Dim part As WorksheetPart = workbookPart.GetPartById(sID)
Dim actualSheet As Worksheet = part.Worksheet
Dim sheetData As SheetData = part.Worksheet.Elements(Of SheetData)().First
For Each r As Row In sheetData.Elements(Of Row)()
For Each c As Cell In r.Elements(Of Cell)()
text = c.CellValue.Text
Console.Write(text & " ")
Next
Next
Next
End Using
Console.Read()
这里是一个方便的辅助方法来获得对应于WorksheetPart图纸:
Sheet sheet = GetSheetFromWorkSheet(myWorkbookPart, myWorksheetPart);
string sheetName = sheet.Name;
:
public static Sheet GetSheetFromWorkSheet
(WorkbookPart workbookPart, WorksheetPart worksheetPart)
{
string relationshipId = workbookPart.GetIdOfPart(worksheetPart);
IEnumerable<Sheet> sheets = workbookPart.Workbook.Sheets.Elements<Sheet>();
return sheets.FirstOrDefault(s => s.Id.HasValue && s.Id.Value == relationshipId);
}
然后你可以从表名称属性获取名称
...这将成为所提及的“标签名称”OP。
备案相反的方法看起来像:
public static Worksheet GetWorkSheetFromSheet(WorkbookPart workbookPart, Sheet sheet)
{
var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
return worksheetPart.Worksheet;
}
...与我们还可以添加下面的方法:
public static IEnumerable<KeyValuePair<string, Worksheet>> GetNamedWorksheets
(WorkbookPart workbookPart)
{
return workbookPart.Workbook.Sheets.Elements<Sheet>()
.Select(sheet => new KeyValuePair<string, Worksheet>
(sheet.Name, GetWorkSheetFromSheet(workbookPart, sheet)));
}
现在你可以很容易地枚举通过所有工作表,包括他们的名字。
把它全部转换成字典基于域名的查询,如果你喜欢的是:
IDictionary<string, WorkSheet> wsDict = GetNamedWorksheets(myWorkbookPart)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
...或者如果你只是想通过名字一个特定表:
public static Sheet GetSheetFromName(WorkbookPart workbookPart, string sheetName)
{
return workbookPart.Workbook.Sheets.Elements<Sheet>()
.FirstOrDefault(s => s.Name.HasValue && s.Name.Value == sheetName);
}
(然后调用GetWorkSheetFromSheet
得到相应的工作表。)
这应该是正确的解决方案。 –
辉煌..谢谢! – Jason
http://msdn.microsoft.com/en-us/library/bb507946。 aspx –
工作正常,如果我只是想拉出标签名称..我可以通过解析出内部/外部xml ..但我想在我自己的For循环..我无法访问表而im在SheetData级别.. – Kwalke001
您无法使用“工作表”对象获取其名称?该页面上的最后一个代码示例显示了如何循环显示表单的属性:大概表单名称是这些属性之一(尽管我自己没有经验)。 –