2011-09-21 74 views
9

我有一个电子表格文档,其中有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属性选项卡名称在电子表格中循环时,它不会以正确的顺序获得标签名称。

+0

http://msdn.microsoft.com/en-us/library/bb507946。 aspx –

+0

工作正常,如果我只是想拉出标签名称..我可以通过解析出内部/外部xml ..但我想在我自己的For循环..我无法访问表而im在SheetData级别.. – Kwalke001

+0

您无法使用“工作表”对象获取其名称?该页面上的最后一个代码示例显示了如何循环显示表单的属性:大概表单名称是这些属性之一(尽管我自己没有经验)。 –

回答

15

的片材的名称被存储在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++; 
} 
+0

这是一个很好的解决方案。谢谢阿穆拉! – Kwalke001

+3

根据我的经验,使用您的代码片段,sheetName以正确的顺序(如它们在文件中)读取表名,但sheetData不按照它们在Excel文件中的顺序读取。结果代码导致所有工作表的混合名称。 – Skull

+2

似乎问题来自“excel_file.xlsx \ xl \ _rels \ workbook.xml.rels”文件,该文件具有电子表格名称和对以某种随机顺序存储的电子表格内容的引用。如果您手动将它们从1重新排序到N(Id =“rId1”,Id =“rId2”,...,Id =“rIdN”),电子表格名称将在读取文件后与其内容对齐。不知道如何在代码中处理这个问题。 – Skull

0
worksheet.GetAttribute("name","").Value 
4
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() 
+2

如果您可以添加一些关于代码之外的原因的讨论,那将会很棒。 – ASGM

+0

这种方式对我来说更有意义,因为您通过名称搜索工作表,获取工作表的ID,然后根据名称获取工作表(使用linq意味着您根本不需要循环) 。标记为答案的答复使用需要循环播放的索引,直到找到所需内容为止。 – wavydavy

21

这里是一个方便的辅助方法来获得对应于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得到相应的工作表。)

+2

这应该是正确的解决方案。 –

+0

辉煌..谢谢! – Jason

相关问题