2015-06-12 2 views
1

Я пытаюсь использовать DocumentFormat.OpenXml для чтения загруженного файла Excel. Когда я получаю файл (HttpPosteFileWrapper), я просто пытаюсь прочитать ячейки и записать их в текстовую строку. (Позже я буду делать больше, но я просто пытаюсь привыкнуть к OpenXml прямо сейчас.)Пытаясь прочитать поток файлов файлов Excel в C#, я получаю числа вместо текста

Мои данные в Excel выглядит примерно так:

Field1 - Field2 - Телефон - Город
IT отдел - EMP - 7175551234 - Springfield
HR - EMP - 7175556543 - W Springfield

код выглядит следующим образом:

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, 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, \ г \ п
53,46,47,48,555, \ г \ п

Похоже, числовые значения приходят через. Это потому, что я использую неправильный тип потока?

Редактировать: Я обновил свой код, чтобы теперь выглядеть так, но он все еще не работает правильно. Мне кажется, нет никакого способа увидеть текстовые данные.

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(); 
} 
} 
} 

Фактические данные 1-й строке файла:
AddressDescription, Адрес1, ADDRESS2, город, штат, почтовый индекс, COUNTRYCODE, электронная почта, мобильный телефон, HomePhone, WorkPhone, факс, OrganizationName, отдел, должность, StartDate, EndDate, 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». Кроме того, где вы говорите theCell.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(); 
     } 

 Смежные вопросы

  • Нет связанных вопросов^_^