C# open xml не может прочитать строковые значения

Привет, я использую открытый XML для чтения Excel в своем приложении .Net. У меня есть метод, который принимает строки и столбцы в качестве входных параметров и возвращает значение для этой конкретной ячейки. Ниже моя реализация.

public List<ServicePortDto> GetServicePorts(IFormFile formFile, Dictionary<string, int> starRowForPorts)
{
    using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(formFile.OpenReadStream(), false))
    {
        WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
        List<int> portRows = new();
        int counter = 0;
        IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
        foreach (var sheet in sheets)
        {
            int startRowPort = starRowForPorts.Where(x=>x.Key == sheet.Name.Value).Select(x => x.Value).FirstOrDefault();
            string relationshipId = sheet.Id.Value;
            WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
            Worksheet workSheet = worksheetPart.Worksheet;
            SheetData sheetData = workSheet.GetFirstChild<SheetData>();
            IEnumerable<Row> rows = sheetData.Descendants<Row>();
            rows = rows.Where(x=>x.RowIndex >= startRowPort);
            foreach (Row row in rows)
            {
                if (row.RowIndex >= startRowPort)
                {
                    string portName = GetCell(workSheet, "B", startRowPort).InnerText;

                    if (portName != null)
                    {
                        counter = counter + 1;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
    }
    return new List<ServicePortDto>();
}

Ниже приведен метод GetCell.

private static Cell GetCell(Worksheet worksheet, string columnName, int rowIndex)
{
    Row row = worksheet.GetFirstChild<SheetData>().Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);

    if (row != null)
    {
        return row.Elements<Cell>().FirstOrDefault(c => string.Compare(c.CellReference.Value, columnName + rowIndex, true) == 0);
    }
    return null;
}

Проблема с вышеуказанным методом заключается в том, что если в ячейке есть какие-либо строковые данные, они читаются как целое число. Я не уверен, почему это происходит. Целочисленные значения читаются правильно. Проблема только со строковыми/текстовыми полями. Могу ли я узнать, чего мне здесь не хватает? Может кто-нибудь помочь мне с этим? Любая помощь будет оценена по достоинству. Спасибо

Вместо использования низкоуровневого пакета Open XML SDK используйте такую ​​библиотеку, как ExcelDataReader, EPPlus или одну из многих библиотек Excel в NuGet. Для того, что вы пытаетесь сделать, может потребоваться только одна строка. Кстати, что ты пытаешься сделать? Чтение одной ячейки во всех библиотеках тривиально и бесполезно.

Panagiotis Kanavos 06.03.2024 10:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
92
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В Open XML значения ячеек хранятся как общие строки или непосредственно как встроенные строки, и вам необходимо обращаться с ними соответствующим образом.

private static string GetCellValue(Cell cell, SharedStringTablePart stringTablePart)
{
    if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
    {
        if (stringTablePart != null)
        {
            SharedStringItem sharedStringItem = stringTablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(int.Parse(cell.InnerText));
            return sharedStringItem.Text?.Text;
        }
    }
    else if (cell.CellValue != null)
    {
        return cell.CellValue.Text;
    }
    return null;
}

Привет @FortyTwo, спасибо за ответ. Если в моем Excel несколько листов, что мне следует передать вышеуказанному методу? можно ли передать рабочий лист вышеуказанному методу?

Niranjan 06.03.2024 10:15

Вместо Open XML SDK используйте одну из библиотек Excel высокого уровня в NuGet, например ExcelDataReader, EPPlus, ClosedXML и многие другие (некоторые из них намного быстрее). Open XML SDK имеет очень низкий уровень, почти на уровне элементов XML.

Например, используя EPPlus, весь этот код можно заменить просто:

using var fileStream=formFile.OpenReadStream();
using ExcelPackage package = new ExcelPackage(fileStream);
ExcelWorksheet sheet = package.Workbook.Worksheets[0];

var range=sheet.Cells["b:b"];
foreach(var cell in range)
{
    ...
}

Вы можете использовать LINQ для подсчета непустых ячеек:

var filledCount=sheet.Cells["b:b"].Where(c=>c.Value!=null).Count();

ExcelDataReader создает оболочку IDbDataReader над листом Excel, которую можно использовать для чтения данных в DataTable, отправки в базу данных и т. д.:

using var reader = ExcelReaderFactory.CreateReader(fileStream);
do
{
    while (reader.Read())
    {
        if (!reader.IsDbNull(1))
        {
        ...
        }
    }
}

Вы можете использовать это средство чтения с SqlBulkCopy для импорта данных в SQL Server:

using var bcp = new SqlBulkCopy(connection);
bcp.DestinationTableName = "SomeTable"; 
...
bcp.WriteToServer(reader); 

Для EPPlus требуется коммерческая лицензия, а для OpenXML SDK — лицензия MIT. Просто добавьте этот комментарий сюда, чтобы, если кто-то выберет это решение, он знал об этом;).

FortyTwo 06.03.2024 11:02

@FortyTwo, комментарий неточный. Это двойной, а не коммерческий подход. ClosedXML и ExcelDataReader — это MIT. Все библиотеки имеют лицензии, включая Open XML SDK. . В любом случае вы платите за Open XML SDK своим (или, скорее, компанией) потерянным временем и доходом. В NuGet много библиотек Excel, они намного меньше и быстрее, чем Open XML SDK.

Panagiotis Kanavos 06.03.2024 11:22

Другие вопросы по теме

Похожие вопросы