Проблема с пропуском пустых ячеек при импорте данных из файла .xlsx в приложение asp.net c # - PullRequest
1 голос
/ 28 октября 2010

У меня проблема с чтением файлов .xlsx в приложении asp.net mvc2.0 с использованием c #. Проблема возникает при чтении пустой ячейки из файла .xlsx. Мой код просто пропускает эту ячейку и читает следующую.

Например, если содержимое файла .xlsx:

FirstName   LastName   Age
John                   36

Они будут читаться как:

FirstName   LastName   Age
John        36

Вот код, который читает.

        private string GetValue(Cell cell, SharedStringTablePart stringTablePart)
    {
        if (cell.ChildElements.Count == 0)
            return string.Empty;

        //get cell value
        string value = cell.ElementAt(0).InnerText;//CellValue.InnerText;

        //Look up real value from shared string table
        if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
            value = stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;

        return value;
    }



        private DataTable ExtractExcelSheetValuesToDataTable(string xlsxFilePath, string sheetName)
    {
        DataTable dt = new DataTable();

        using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(xlsxFilePath, true))
        {
            //Access the main Workbook part, which contains data
            WorkbookPart workbookPart = myWorkbook.WorkbookPart;
            WorksheetPart worksheetPart = null;

            if (!string.IsNullOrEmpty(sheetName))
            {
                Sheet ss = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).SingleOrDefault<Sheet>();
                worksheetPart = (WorksheetPart)workbookPart.GetPartById(ss.Id);
            }
            else
            {
                worksheetPart = workbookPart.WorksheetParts.FirstOrDefault();
            }

            SharedStringTablePart stringTablePart = workbookPart.SharedStringTablePart;
            if (worksheetPart != null)
            {
                Row lastRow = worksheetPart.Worksheet.Descendants<Row>().LastOrDefault();
                Row firstRow = worksheetPart.Worksheet.Descendants<Row>().FirstOrDefault();

                if (firstRow != null)
                {
                    foreach (Cell c in firstRow.ChildElements)
                    {
                        string value = GetValue(c, stringTablePart);
                        dt.Columns.Add(value);
                    }
                }

                if (lastRow != null)
                {
                    for (int i = 2; i <= lastRow.RowIndex; i++)
                    {
                        DataRow dr = dt.NewRow();
                        bool empty = true;
                        Row row = worksheetPart.Worksheet.Descendants<Row>().Where(r => i == r.RowIndex).FirstOrDefault();

                        int j = 0;
                        if (row != null)
                        {
                            foreach (Cell c in row.ChildElements)
                            {
                                //Get cell value
                                string value = GetValue(c, stringTablePart);
                                if (!string.IsNullOrEmpty(value) && value != "")
                                    empty = false;

                                dr[j] = value;
                                j++;
                                if (j == dt.Columns.Count)
                                    break;
                            }

                            if (empty)
                                break;

                            dt.Rows.Add(dr);
                        }
                    }
                }
            }
        }

        return dt;

    }

Ответы [ 2 ]

1 голос
/ 28 декабря 2010

У меня была такая же проблема.Это моя тренировка:

 int offset = GetColDiff(lastCol, cell.CellReference);

     //filling empty columns
     while (offset-- > 1)
        dt.Rows[rowCounter][cnt++] = DBNull.Value;
     //filling regular column
     dt.Rows[rowCounter][cnt++] = value;

   lastCol = cell.CellReference;

******************
//calculating column distance
    int GetColDiff(string prev, string curr)
    {
        int i=0;
        int index1 = 0;
        int index2 = 0;

        while (prev!="0" && prev.Length>i && Char.IsLetter(prev[i]))//prev=="0"-startingcondition
        {
            index1 += ('Z' - 'A' + 1) * index1 + (prev[i] - 'A');
            i++;
        }
        i = 0;
        while (curr.Length>i && char.IsLetter(curr[i]))
        {
            index2 += ('Z' - 'A'+ 1) * index2 + (curr[i] - 'A');
            i++;
        }
        return index2 - index1;
    }
1 голос
/ 12 ноября 2010

Мое решение этой проблемы не так элегантно, как некоторые могут использовать.
Сначала я сопоставляю столбцы с символами (A, B, C, D и т. Д.), Чтобы знать, что FirstName = A, LastName = B и Age = C.

Далее, я просматриваю dataCells, чтобы увидеть, есть ли ячейка со ссылкой на Age. Если есть ссылка на ячейку Age, я проверю тип данных ячейки.

ex: dataCells.Where (x => x.CellReference.Value.Contains (cellIndex)). First (). DataType == CellValues.SharedString)

В этом случае cellIndex будет = 'C'.

Если предыдущий запрос linq имеет значение true, то вы перейдете в таблицу sharedString и найдете значение для возраста по CellReference.

var age = sharedStrings.ChildElements [int.Parse (dataCells.Where (x => x.CellReference.Value.Contains (cellIndex)). FirstOrDefault (). InnerText)]. InnerText;

Вашей проблемы со случайной установкой LastName (столбец B) на любой возраст (столбец C) следует избегать, если вы отрабатываете ссылку на ячейку для каждой строки данных.

Примечание: я только что натолкнулся на то, что пустые ячейки в Excel хранятся двумя разными способами. Иногда есть ссылка на индекс SharedStringTable (cell.DataType = "s" и cell.InnerText = "37"), а иногда ячейка просто пуста (cell.DataType = null и cell.InnerText = "").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...