Практическое .NET Core 🚀 - напишите парсер, сборщик и парсер .xls (x). Часть 3: ПАРСЕР

… Или как кросс-платформенный 🌎 с легкостью анализировать документ Excel!

Привет dev! Думаю, тебе не только солнечно, но и очень повезло! Хм. Что ж, здесь вы не выиграли в лотерею. Извините, но ... надеюсь, это ваш ... ТРЕТИЙ раз, когда вы очень стараетесь подыгрывать .NET Core. Под игрой я подразумеваю, что вы уже освоили парсинг и получение данных из Интернета. Конечно, это то, с чем вы столкнулись в Части 1 и Части 2 этой серии. Так что да, если вы все еще хотите построить что-то бетонное (но мягкое!), Это будет здорово! Кроме того ... делать это голыми руками программиста, ох. Повезло тебе! Ты жжешь! 🎸 Давай поиграем еще ... 👶

В этой статье объясняется, как анализировать (в модели C #) несколько документов Excel (.xls и .xlsx) эффективным и кроссплатформенным способом. Мы будем использовать пакет NuGet NPOI для обработки синтаксического анализа и оптимизации процесса - старый добрый TPL, который мы рассмотрели в предыдущих статьях. Что действительно замечательно в этой части, так это то, что библиотека NPOI работает без поддержки COM-взаимодействия для Microsoft Excel. Это означает, что мы можем безопасно запускать наше приложение синтаксического анализатора в Windows, Mac или Linux, не беспокоясь о том, установлен ли у нас Excel (поскольку это был бы обычный и более устоявшийся способ синтаксического анализа с полной платформой .NET).

Исходный код этой статьи доступен в моем репозитории GitHub.

Вы знаете упражнение, давайте добавим немного силы инициации

Начнем с создания класса парсера. Этот класс будет обрабатывать всю обработку документов Excel, которые мы получили в предыдущей статье. Итак, перейдите в MedsProcessor.Parser и добавьте новый класс с именем HzzoExcelParser. К настоящему времени вы, возможно, уже догадались, как выглядит такой причудливый начальный вид наших основных классов обработки, которые мы добавляем, но, тем не менее ... он должен выглядеть примерно так:

Это будет наша начальная установка. У класса будет только один внешний метод, который синтаксический анализатор будет вызывать для обработки синтаксического анализа с помощью библиотеки NPOI. Следующее, что нужно сделать, это добавить в наше решение эту загадочную библиотеку NPOI. Но перед этим… вкратце об этом. Библиотека была разработана (или / и поддерживается, IDK 😞?) Изначально Тони Ку, которую можно прочитать на никогда не умирающем и бесконечном сайте codeplex. Вы можете прочитать, что это адаптация Java’s POI library, которая сама по себе является библиотекой адаптера для взаимодействия с документами Microsoft Office, включая Excel. К счастью, тем временем он был принят сообществом dotnetcore github repo и адаптирован для .NET Core! И это мои дамы 💃 и господа 🎩 превосходно 🌟 для нашего текущего сценария. Вы так не думаете? Лучше сделай это или брось сейчас же!

Установка NPOI для разбора некоторых нахальных файлов Excel

Позвольте мне быть скучным (снова) и вежливо спросить вас. Вы помните, как использовали более 9000 dotnet CLI? Почему, конечно, вы делаете! 🤓 Итак, перейдите / cd в каталог MedsProcessor.Parser и добавьте пакет NPOI следующим образом:

> cd MedsProcessor.Parser
> dotnet add package DotNetCore.NPOI
> dotnet restore
> cd ..

Ура! Теперь можно приступить к работе с тяжелыми грузами 💪.

Пошаговая логика парсера (с предположениями) 👣

Так что эти предположения будут очень важны при сборке нашего парсера. И почему так? Что ж, если вы стремитесь к давнему синтаксическому анализатору, то есть инструменту, который может выдерживать будущие изменения целевых документов, которые вы анализируете, вам лучше создавать его с учетом этой гибкости. Я имею в виду, что вы, вероятно, уже привыкли писать тонны if циклов, и вот что из этого получится. Но в этом сценарии это значительно увеличило бы нашу кодовую базу. Мы будем добавлять поисковые запросы для наших столбцов заголовков, которые будут включать скучные хорватские слова, которые вызовут у вас напряжение. Так что просто ради того, чтобы не делать этот учебник… чрезвычайно (Боже я ненавижу это слово) огромным и чрезмерно раздутым кодом, я сделал несколько (не дай Бог) жестко закодированных предположений. Я советую вам не делать этого в ваших производственных / реальных сценариях. Я имею в виду, что вы взрослый человек, готовый поддержать ваши действия? 😅 ОК. И да, чистый код, SRP, SOLID, ну знаете, хорошие вещи. Под предположениями я не имею в виду ничего необычного, а просто факт я ожидаю, что некоторые индексы будут указывать на ожидаемые данные в предполагаемом порядке во время процесса синтаксического анализа одной строки Excel. Чтобы заставить эту мировую машину судьбы работать, нам нужно несколько молитв 🙏… JK, нам просто нужен код. Так…

Метод Run будет очень простым и запустит асинхронный (на этот раз мы перейдем полностью асинхронно, потому что я читал этот шедевр, и вам тоже следует!) параллельный процесс 4 разных сценария, которые пройдёт наш парсер:

Итак, здесь вы можете видеть, что мы добавили служебный метод потоковой передачи StartLongRunning, который является всего лишь ярлыком для запуска длительной работы. Если вы недоумеваете, почему именно TaskCreationOptions.LongRunning, это логично. Короче говоря, если побочная работа занимает больше секунды (я знаю практическое правило 🔥 🚒, и ваш внутренний инженер сейчас удивительно оскорблен 😡, мне все равно! 🌝), вы может подумать о том, чтобы начать это так. Подробнее по теме на MSDN.

Вышеупомянутые пошаговые методы синтаксического анализатора фактически просто выбирают подмножества коллекции meds и передают их одному универсальному методу синтаксического анализатора с именем ParseHzzoExcelDocuments. Общий синтаксический анализатор будет обрабатывать подмножества параллельно, чтобы сделать работу немного быстрее. Думаю, это было бы нормально. 🙂

Четыре метода должны выглядеть примерно так:

Хорватские слова, которые вы видите в Contains призывах, в основном разделяют список лекарств на основной и дополнительный. Кроме того, мы использовали статический член DateTime filterDtStartWith2014, чтобы указать разницу в структуре документа Excel. Это означает, что документы до 2014–02 имеют другой порядок столбцов, чем документы после этого времени, и мы должны следовать этому сценарию с другой логикой синтаксического анализатора (допущения). Таким образом, вся эта логика «обработки» специфична для этого специфического набора данных. Даже если вы можете назвать это набором данных. Мне сказали, что на самом деле (то есть на реальной работе) может быть еще хуже, чем это. 😄 Ааа. Ага. Мычание оооон. 🚂 Бей, бей!

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

Моделирование данных импорта ⛸

Как уже упоминалось, нам нужен импортный DTO. А еще нам понадобится коллекция тех, что есть в нашем уже известном HzzoMedsDownloadDto. Начнем с добавления нового типа класса DTO в проект MedsProcessor.Common в каталоге Models с именем HzzoMedsImportDto. Ниже вы найдете результат тяжелого анализа работы 🔎 Я проделал для вас, чтобы вы могли просто погрузиться в сам процесс импорта. Итак, да, новый HzzoMedsImportDto должен выглядеть так, с некоторыми недостающими перечислениями, которые мы рассмотрим:

Возможно, вам не хватает некоторых using директив вверху, поэтому, пожалуйста, разрешите их в первую очередь, да, сделайте это самостоятельно, братан! 📝 Хорошо. Наконец-то я заставил тебя написать код. Вы могли чему-то научиться! 👏 Те, которые вы не смогли разрешить, это недостающие, связанные с несуществующими перечислениями. 😲 Итак, давайте исправим это, создав новый файл класса в корне проекта (то есть вне каталога Models) с именем Enums.cs. Файл класса Enums не будет содержать классов, но будет содержать несколько определений типов перечислений, которых нам не хватает в новом импорте DTO.

Enums.cs будет содержать различные перечисления, которые я собрал для вас. Эта сборка была сделана в ходе многочисленных попыток парсинга. Собственно через пару дней… Пока мне не удалось сопоставить все комбинации перечислений. Вы можете увидеть это, если немного пролистаете определения. Мы будем использовать декоратор атрибутов C # [Flags] для типов перечислений. Это позволяет нам в основном создавать комбинации значений перечисления, и это как раз то, что нам нужно. Комбинирование значений перечисления возможно с помощью бинарных операторов (таких как & и |) над целочисленным значением поддержки перечисления. Чтобы управлять этим удобным для человека способом, мы будем использовать десятичные представления двоичных чисел, то есть 0, 1, 2, 4, 8, 16, 32… так что вы получите картину. Вы просто (черт возьми, как инженер, я ненавижу это слово даже больше, чем ужасно, не так ли?) Умножаете число 2 (начиная с 2, конечно). Ах, сам файл, да, он должен выглядеть так:

О, я также приложил дополнительные усилия, чтобы так любезно… перевести кое-что на английский! 🙇 Чтобы не запутаться в таком скучном хорватском языке 😶. Я имею в виду, что это не так, но то, что я слышал от чужестранцев, - это то, что бороться с ними довольно сложно ⚔️. Что… не является поводом для того, чтобы не посещать, например, Город Задар на побережье Хорватии! 🍉

Большой! Теперь у нас есть импортный DTO, и вам нужно проверить этот процесс импорта / парсера, который вы запустили в файле HzzoExcelParser.cs. На данный момент у вас должен отсутствовать только (хе-хе) основной метод синтаксического анализатора с именем ParseHzzoExcelDocuments.

Использование NPOI для анализа документа Excel

Библиотека NPOI работает довольно просто. ✨ Мы представим вспомогательный метод static, который откроет книгу Excel и ее первый рабочий лист. Имя метода будет OpenWorkbookSheetWithNpoi и должно выглядеть так:

Предыдущий метод обрабатывает два сценария, то есть типы документов .xls и .xlsx. В зависимости от того, какой из них выбран, нужен другой конструктор. Для .xls - new HSSFWorkbook(stream), для .xlsx - new XSSFWoorkbook(stream). Свойству HzzoMedsDownloadDto.Href также потребуется общедоступный установщик, поскольку в настоящий момент он должен был быть internal по какой-то несуществующей причине. 😕 Для вызова упомянутых конструкторов NPOI вам необходимо добавить директивы NPOI using в начало документа. Все необходимые вам варианты использования (и MedsProcessor.Common.Extensions будут отсутствовать):

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MedsProcessor.Common.Extensions;
using MedsProcessor.Common.Models;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;

Ну и напоследок пикантная 🍹 часть статьи. Основной метод обработки будет включать в себя множество закрывающих функций, которые помогут нам справиться с чтением различных типов данных в модель C #. Функции были специально выбраны для замыкания, поэтому нам не нужно постоянно передавать индексы строк и столбцов с помощью ref. Замыкания будут определены как локальные функции, которые являются новой функцией C # 7.0. Будьте очень осторожны при выполнении чувствительных к памяти вещей с закрывающими локальными функциями, поскольку они могут вызвать некоторые утечки, как объясняет здесь Игорь Рончевич.

Метод ParseHzzoExcelDocuments megamoth 🦋 🔥 должен выглядеть так:

… Ааааа и все равно не пойдет! 😉 Вы заметите, что чего-то не хватает. Нам нужно создать новый файл класса EnumExtensions.cs, который будет определять дополнительный метод Parse<T1, T2>(string input). Итак, давайте сделаем это в корне MedsProcessor.Common, добавив новый dir Extensions и создав в нем файл класса:

Хороший! Есть еще кое-что, что нужно добавить. В фантазии 👖 HzzoMedsDownloadDto нам не хватает важной коллекции, то есть MedsList. Так что зайдите в файл класса и следующую строку:

public ISet<HzzoMedsImportDto> MedsList { get; } = new HashSet<HzzoMedsImportDto>();

И это должно сделать это, мой дорогой друг! 🙇 👏

Завершите AppController.cs и протестируйте парсер

Чтобы заставить эту машину работать с наркотиками, нам все еще не хватает некоторых настроек DI. Перейдите в Startup.cs и добавьте следующую строку в метод ConfigureServices (а также вам понадобятся директивы using, но вы уже привыкли к этой древней технике пыток 🔨 🤕):

services.AddSingleton<HzzoExcelParser>();

Превосходно! 😺 Почти готово !! Еще один шаг - обновить наш AppController.cs, чтобы мы действительно запускали процессор синтаксического анализа. Чтобы сэкономить ваше время в n-й раз, AppController теперь должен выглядеть следующим образом (и на этот раз будет включать некоторую полезную информацию о процессе):

Потрясающие! ⭐️ Чтобы проверить, все ли сверкает, как звезда, которую я только что спамил, вам нужно снова использовать dotnet CLI и выдать build. Если все идеально и без ошибок (если они есть, исправьте их как можно скорее ⛑), тогда вы можете впоследствии выдать run. Вот и все! И снова хорошая работа, и это уже в третий раз! 👏

Я честно скажу, что это составляет начальную идею этой серии статей. Другие интересные работы по API также будут включены в следующую часть 4, которая будет больше относиться к веб-API, контроллеру, действиям и материалам HTTP.

TL; DR - Итак, вы хотите разобрать Excel 👍

В этой статье у вас была прекрасная возможность научиться синтаксическому анализу документов Excel с помощью приложения Web API .NET Core, используя кроссплатформенную библиотеку пакетов NPOI NuGet. Эта статья является продолжением статьи 2, в которой нам были предоставлены загруженные документы Excel, которые мы планировали проанализировать. Библиотека NPOI позволила нам без каких-либо проблем выполнять синтаксический анализ между форматами .xls и .xlsx и читать книгу и ее рабочие листы. И мы сделали это, не установив Microsoft Excel в нашей ОС. Мы жестко запрограммировали много вещей в этом руководстве (основной метод синтаксического анализа), поскольку создание ifology для выбора ячеек Excel здесь не является основной проблемой. Используя предположения о том, какой столбец сопоставляется с данными модели C #, мы использовали локальные функции из C # 7.0 для создания замыканий, которые помогли нам быстро анализировать данные ячеек и в то же время продвигать наш индекс строки и столбца. Коротко, просто и мило! 💸

ОБНОВЛЕНИЕ:

Если вы ищете последнюю часть 4, ссылка находится здесь: https://medium.com/@vekzdran/practical-net-core-write-a-web-scraper-fetcher- excel-parser-part-4-secure-rest-web-api-b07d002c0bac

Надеюсь, это в третий раз было полезным и вы узнали что-то новое. Если вам понравилось то, что вы прочитали, оставьте комментарий, критику, смайлик или поделитесь этим как-нибудь или как вам лучше всего, спасибо!

… О, и не забудь похлопать 👏, по крайней мере, себе за то, что добрался до сюда! Опять таки!! 😜