697ae44519
- Загрузка одного .xlsx (СПРАВКА + Лист1 в одном файле) - Рег. номера берутся из СПРАВКА автоматически, группируются по (ТН ВЭД, Страна) - Отдельный опциональный справочник кодов (CodesImportService) - Фильтры: Все / Авто / Проверить / Нет кода / Без нетто - Таблица сразу отсортирована по ТН ВЭД с живым обновлением п/п - Начальный п/п: поле в UI, автоинкремент после экспорта - Лист2: рамки, жёлтая строка при >1 рег. номере, итого по кол-ву - Лист3: ТН ВЭД в колонке B вместо константы 09035 - Красный ErrorMessage под кнопкой загрузки, удалён SpravkaFileEntry
121 lines
3.4 KiB
C#
121 lines
3.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.RegularExpressions;
|
|
using ClosedXML.Excel;
|
|
using DeclarationAutomatization.Models;
|
|
|
|
namespace DeclarationAutomatization.Services;
|
|
|
|
public class Sheet1ImportService
|
|
{
|
|
private const string SheetName = "Лист1";
|
|
private const string ItogoMarker = "ИТОГО";
|
|
|
|
public List<Sheet1Group> ReadSheet1(string filePath)
|
|
{
|
|
using var workbook = new XLWorkbook(filePath);
|
|
|
|
IXLWorksheet? sheet = null;
|
|
foreach (var ws in workbook.Worksheets)
|
|
{
|
|
if (ws.Name.Equals(SheetName, StringComparison.OrdinalIgnoreCase))
|
|
{ sheet = ws; break; }
|
|
}
|
|
|
|
if (sheet == null)
|
|
throw new InvalidOperationException($"Лист '{SheetName}' не найден в файле: {filePath}");
|
|
|
|
var groups = new List<Sheet1Group>();
|
|
int sequentialNumber = 1;
|
|
int lastRow = sheet.LastRowUsed()?.RowNumber() ?? 1;
|
|
|
|
for (int r = 1; r <= lastRow; r++)
|
|
{
|
|
var row = sheet.Row(r);
|
|
if (!IsItogoRow(row)) continue;
|
|
|
|
var group = BuildGroup(row, sequentialNumber);
|
|
if (group != null)
|
|
{
|
|
groups.Add(group);
|
|
sequentialNumber++;
|
|
}
|
|
}
|
|
|
|
return groups;
|
|
}
|
|
|
|
private static bool IsItogoRow(IXLRow row)
|
|
{
|
|
foreach (var cell in row.CellsUsed())
|
|
{
|
|
if (cell.GetString().Contains(ItogoMarker, StringComparison.OrdinalIgnoreCase))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static Sheet1Group? BuildGroup(IXLRow row, int sequentialNumber)
|
|
{
|
|
string tnVed = FindTnVed(row);
|
|
if (string.IsNullOrWhiteSpace(tnVed)) return null;
|
|
|
|
string description = row.Cell(2).GetString().Trim();
|
|
if (string.IsNullOrWhiteSpace(description))
|
|
description = row.Cell(3).GetString().Trim();
|
|
|
|
string countryId = FindCountryId(row);
|
|
|
|
decimal qty = ParseDecimal(row.Cell(9));
|
|
decimal amount = ParseDecimal(row.Cell(10));
|
|
decimal gross = ParseDecimal(row.Cell(11));
|
|
decimal net = ParseDecimal(row.Cell(12));
|
|
|
|
return new Sheet1Group
|
|
{
|
|
SequentialNumber = sequentialNumber,
|
|
Description = description,
|
|
TnVed = tnVed,
|
|
CountryId = countryId,
|
|
Quantity = qty,
|
|
AmountWithVat = amount,
|
|
GrossWeight = gross,
|
|
NetWeight = net,
|
|
};
|
|
}
|
|
|
|
private static string FindTnVed(IXLRow row)
|
|
{
|
|
foreach (var cell in row.CellsUsed())
|
|
{
|
|
var val = cell.GetString().Trim();
|
|
if (Regex.IsMatch(val, @"^\d{10}$"))
|
|
return val;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private static string FindCountryId(IXLRow row)
|
|
{
|
|
foreach (var cell in row.CellsUsed())
|
|
{
|
|
var val = cell.GetString().Trim();
|
|
if (Regex.IsMatch(val, @"^[A-Z]{2}$"))
|
|
return val;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private static decimal ParseDecimal(IXLCell cell)
|
|
{
|
|
if (cell.IsEmpty()) return 0;
|
|
try
|
|
{
|
|
var val = cell.GetString().Trim().Replace(',', '.');
|
|
return decimal.TryParse(val, System.Globalization.NumberStyles.Any,
|
|
System.Globalization.CultureInfo.InvariantCulture, out var d) ? d : 0;
|
|
}
|
|
catch { return 0; }
|
|
}
|
|
}
|