2015-06-12 22 views
1

我試圖使用DocumentFormat.OpenXml來讀取上傳的Excel文件。當我得到文件(HttpPosteFileWrapper)時,我只是試圖讀取單元格並將它們寫入文本字符串。 (後來,我會做更多,但我只是想,現在習慣了OpenXML的。)試圖讀取C#中的Excel文件文件流,我得到的是數字而不是文本

我的數據在Excel中看起來是這樣的:

字段1 - 場2 - 電話 - 市
IT部門 - 員工 - 7175551234 - 斯普林菲爾德
人力資源 - 員工 - 7175556543 - 含春

代碼如下所示:

var doc = SpreadsheetDocument.Open(file.InputStream, false); 
WorkbookPart workbookPart = doc.WorkbookPart; 
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); 
SheetData thisSheet = worksheetPart.Worksheet.Elements<SheetData>().First(); 
System.Text.StringBuilder text = new System.Text.StringBuilder(); 
foreach (Row r in thisSheet.Elements<Row>()) 
{ 
    foreach (Cell c in r.Elements<Cell>()) 
    { 
     text.Append(c.CellValue.Text + ","); 
    } 
    text.AppendLine(); 
} 

並創建字符串看起來是這樣的:

49,51,50,0,1,2,3,4,5,6,7,8,9,10,11,12, 13,16,14,15,17,18,19,20,21,22,40,41,42,43,44,45,54,\ r \ n
52,24,23,25,26, 27,7306,33,28,29,30,31,17033,32,34,7175555555,7175551234,7175554321,7175550000,35,36,37,36526,40179,38,39,30,31,17033,32, 55,\ r \ n
53,46,47,48,555,\ r \ n

這似乎是數值才能通過。是否因爲我使用錯誤的流類型?

編輯:我已經更新了我的代碼,現在看起來像這樣,但它仍然無法正常工作。我似乎無法看到文本數據。

public ActionResult ProfileImport(IEnumerable<HttpPostedFileBase> files) 
{ 
    // Build file list 
    int i = 1; 
    foreach (var file in files) 
    { 
     if (file.ContentLength > 0) 
     { 

var doc = SpreadsheetDocument.Open(file.InputStream, false); 
WorkbookPart workbookPart = doc.WorkbookPart; 
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First(); 
SheetData thisSheet = worksheetPart.Worksheet.Elements<SheetData>().First(); 
System.Text.StringBuilder text = new System.Text.StringBuilder(); 
foreach (Row r in thisSheet.Elements<Row>()) 
{ 
    foreach (Cell c in r.Elements<Cell>()) 
    { 
     string value = c.InnerText; 
     if (c.DataType != null && c.DataType.Value == CellValues.SharedString) // Check DataType exists 
     { 
      var stringTable = workbookPart.GetPartsOfType<SharedStringTablePart>() 
       .FirstOrDefault(); // Get Table parts from workbookPart 
      if (stringTable != null) 
       value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText; 
      text.Append(value + ","); 
     } 
     else 
      text.Append(value + ","); 
    } 
    text.AppendLine(); 
} 
var outText = text.ToString(); 
} 
} 
} 

從文件的第一行實際數據:
AddressDescription,地址1,地址,城市,州,郵編,COUNTRYCODE,電子郵件,手機,HOMEPHONE,辦公電話,傳真,單位名稱,部門,職位,起始日期,結束日期,OrganizationAddress1,OrganizationAddress2 OrganizationCity,OrganizationState,OrganizationPostalCode,OrganizationCountryCode,關鍵詞

該行的Row.InnerText:
「495150」

Row.OuterXml:

"<x:row r=\"1\" spans=\"1:33\" s=\"3\" customFormat=\"1\" x14ac:dyDescent=\"0.25\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"> 
    <x:c r=\"A1\" s=\"3\" t=\"s\"><x:v>49</x:v></x:c> 
    <x:c r=\"B1\" s=\"3\" t=\"s\"><x:v>51</x:v></x:c> 
    <x:c r=\"C1\" s=\"3\" t=\"s\"><x:v>50</x:v></x:c> 
    <x:c r=\"D1\" s=\"3\" t=\"s\"><x:v>0</x:v></x:c> 
    <x:c r=\"E1\" s=\"3\" t=\"s\"><x:v>1</x:v></x:c> 
    <x:c r=\"F1\" s=\"3\" t=\"s\"><x:v>2</x:v></x:c> 
    <x:c r=\"G1\" s=\"3\" t=\"s\"><x:v>3</x:v></x:c> 
    <x:c r=\"H1\" s=\"3\" t=\"s\"><x:v>4</x:v></x:c> 
    <x:c r=\"I1\" s=\"3\" t=\"s\"><x:v>5</x:v></x:c> 
    <x:c r=\"J1\" s=\"3\" t=\"s\"><x:v>6</x:v></x:c> 
    <x:c r=\"K1\" s=\"3\" t=\"s\"><x:v>7</x:v></x:c> 
    <x:c r=\"L1\" s=\"3\" t=\"s\"><x:v>8</x:v></x:c> 
    <x:c r=\"M1\" s=\"3\" t=\"s\"><x:v>9</x:v></x:c> 
    <x:c r=\"N1\" s=\"3\" t=\"s\"><x:v>10</x:v></x:c> 
    <x:c r=\"O1\" s=\"3\" t=\"s\"><x:v>11</x:v></x:c> 
    <x:c r=\"P1\" s=\"4\" t=\"s\"><x:v>12</x:v></x:c> 
    <x:c r=\"Q1\" s=\"4\" t=\"s\"><x:v>13</x:v></x:c> 
    <x:c r=\"R1\" s=\"3\" t=\"s\"><x:v>16</x:v></x:c> 
    <x:c r=\"S1\" s=\"3\" t=\"s\"><x:v>14</x:v></x:c> 
    <x:c r=\"T1\" s=\"3\" t=\"s\"><x:v>15</x:v></x:c> 
    <x:c r=\"U1\" s=\"3\" t=\"s\"><x:v>17</x:v></x:c> 
    <x:c r=\"V1\" s=\"3\" t=\"s\"><x:v>18</x:v></x:c> 
    <x:c r=\"W1\" s=\"3\" t=\"s\"><x:v>19</x:v></x:c> 
    <x:c r=\"X1\" s=\"3\" t=\"s\"><x:v>20</x:v></x:c> 
    <x:c r=\"Y1\" s=\"3\" t=\"s\"><x:v>21</x:v></x:c> 
    <x:c r=\"Z1\" s=\"3\" t=\"s\"><x:v>22</x:v></x:c> 
    <x:c r=\"AA1\" s=\"3\" t=\"s\"><x:v>40</x:v></x:c> 
    <x:c r=\"AB1\" s=\"3\" t=\"s\"><x:v>41</x:v></x:c> 
    <x:c r=\"AC1\" s=\"3\" t=\"s\"><x:v>42</x:v></x:c> 
    <x:c r=\"AD1\" s=\"3\" t=\"s\"><x:v>43</x:v></x:c> 
    <x:c r=\"AE1\" s=\"3\" t=\"s\"><x:v>44</x:v></x:c> 
    <x:c r=\"AF1\" s=\"3\" t=\"s\"><x:v>45</x:v></x:c> 
    <x:c r=\"AG1\" s=\"3\" t=\"s\"><x:v>54</x:v></x:c> 
</x:row>" 
+0

已經有一段時間了,因爲我用.net工作過電子表格。我記得使用了Range對象很多。 –

+0

該文件是一個xlsx工作表文件。 –

+0

您是否能夠確定您無法獲取字符串數據的單元格的「DataType」? – maniak1982

回答

2

它看起來像這些指標在共享字符串表中的字符串。在Excel文件格式中,字符串數據存儲在共享字符串表中,然後是單元級別的引用。根據文檔,如果數據類型爲文本,CellValue會返回StringTable的索引。

https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.cellvalue%28v=office.14%29.aspx?f=255&MSPPError=-2147217396

不知道更多關於在你的細胞中的數據類型(有不同的方法來檢索它基於數據類型)。如果它是什麼,我想是的,這將是一個SharedString,您將需要檢索的SharedStringTablePart,如在此MSDN頁:

https://msdn.microsoft.com/en-us/library/hh298534%28v=office.14%29.aspx?f=255&MSPPError=-2147217396

您的代碼將是這個樣子:

foreach (Cell c in r.Elements<Cell>()) 
{ 
    string value = c.InnerText; 
    if (c.DataType.Value == CellValues.SharedString) 
    { 
     var stringTable = worksheetPart.GetPartsOfType<SharedStringTablePart>() 
      .FirstOrDefault(); 
     if (stringTable != null) 
      value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText; 
     text.Append(value + ","); 
    } 
    else 
     text.Append(value + ","); 
    text.AppendLine(); 
} 
+0

謝謝你的代碼示例。然而,雖然單元格確實說他們是SharedString,但StringTable始終爲'null'。此外,你說的Cell.InnerText你的意思是c.InnerText;? –

+0

是的,我做到了!我從我編寫的一些代碼改編來測試共享字符串表假設。但我只是複製了頁面上的代碼,以便讓您有機會看到它。整個邏輯基於來自MSDN鏈接的代碼,該代碼是一個自包含的類,用於從Excel單元格獲取值。如果您要查看該課程,則可能會爲您提取這些值。 – maniak1982

+0

此外,InnerText有時也是正確的數據。如果數據的值是數字,就像電話號碼一樣,InnerText正確地反映了這一點。 –

2

我有同樣的問題,並找到了解決辦法,你只需要添加這個方法,你會得到你所需要的確切的文本,而不是數字:

 private string ReadExcelCell(Cell cell, WorkbookPart workbookPart) 
     { 
      var cellValue = cell.CellValue; 
      var text = (cellValue == null) ? cell.InnerText : cellValue.Text; 
      if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString)) 
      { 
       text = workbookPart.SharedStringTablePart.SharedStringTable 
        .Elements<SharedStringItem>().ElementAt(
         Convert.ToInt32(cell.CellValue.Text)).InnerText; 
      } 
      return (text ?? string.Empty).Trim(); 
     }