680 lines
26 KiB
C#
680 lines
26 KiB
C#
using FATrace.Com;
|
||
using FATrace.Model;
|
||
using NPOI.SS.UserModel;
|
||
using NPOI.XSSF.UserModel;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using System.Timers;
|
||
using FreeSql;
|
||
|
||
namespace FATrace.WPLApp.Services
|
||
{
|
||
/// <summary>
|
||
/// Excel 文件读取与定时导入服务
|
||
/// - 每小时扫描一次源目录中的 *.xlsx 文件(文件名: yyyyMMddHHmmss.xlsx,每天一个)
|
||
/// - 按 Sheet 名映射到对应的 FileModel 实体表
|
||
/// - 使用 FreeSql 批量插入数据
|
||
/// - 导入完成后将文件移动到归档目录,并在 FileImportLog 中记录详细信息
|
||
/// </summary>
|
||
public class ReadFileServices : IDisposable
|
||
{
|
||
private readonly ILogService _log;
|
||
private readonly IFreeSql _fsql;
|
||
|
||
private readonly System.Timers.Timer _timer;
|
||
private readonly string _sourceDirectory;
|
||
private readonly string _archiveDirectory;
|
||
|
||
private bool _disposed;
|
||
private volatile bool _isRunning;
|
||
|
||
/// <summary>
|
||
/// 构造函数:初始化路径配置与定时器
|
||
/// </summary>
|
||
public ReadFileServices(ILogService logService, IFreeSql freeSql)
|
||
{
|
||
_log = logService;
|
||
_fsql = freeSql;
|
||
|
||
// 路径从 App.config 读取,支持相对路径(相对于应用程序根目录)
|
||
var sourceSetting = FATrace.Com.ConfigHelper.GetStringOrDefault("ExcelImportSourceDir", "ExcelFile");
|
||
var archiveSetting = FATrace.Com.ConfigHelper.GetStringOrDefault("ExcelImportArchiveDir", Path.Combine("ExcelFile", "Archive"));
|
||
|
||
_sourceDirectory = ResolvePath(sourceSetting);
|
||
_archiveDirectory = ResolvePath(archiveSetting);
|
||
|
||
try
|
||
{
|
||
Directory.CreateDirectory(_sourceDirectory);
|
||
Directory.CreateDirectory(_archiveDirectory);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"创建 Excel 导入目录失败: src={_sourceDirectory}, archive={_archiveDirectory}, ex={ex.Message}");
|
||
}
|
||
|
||
// 每小时扫描一次(3600000 ms),如有需要可后续改为配置项
|
||
_timer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds)//TimeSpan.FromHours(1).TotalMilliseconds
|
||
{
|
||
AutoReset = true,
|
||
Enabled = true
|
||
};
|
||
_timer.Elapsed += async (s, e) => await OnTimerElapsedAsync().ConfigureAwait(false);
|
||
|
||
// 启动后立即执行一次检查,避免必须等一小时
|
||
Task.Run(async () =>
|
||
{
|
||
try
|
||
{
|
||
await OnTimerElapsedAsync().ConfigureAwait(false);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"Excel 首次导入检查异常: {ex.Message}");
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将配置中的路径转换为绝对路径(支持相对路径)
|
||
/// </summary>
|
||
private static string ResolvePath(string pathSetting)
|
||
{
|
||
var path = (pathSetting ?? string.Empty).Trim();
|
||
if (string.IsNullOrWhiteSpace(path))
|
||
{
|
||
return AppDomain.CurrentDomain.BaseDirectory;
|
||
}
|
||
|
||
// 兼容配置中写成 "C:\Dir" 或 'C:\Dir' 的情况
|
||
if (path.Length >= 2)
|
||
{
|
||
if ((path.StartsWith("\"") && path.EndsWith("\"")) || (path.StartsWith("'") && path.EndsWith("'")))
|
||
{
|
||
path = path.Substring(1, path.Length - 2).Trim();
|
||
}
|
||
}
|
||
|
||
// 支持环境变量:%USERPROFILE%\xxx
|
||
path = Environment.ExpandEnvironmentVariables(path);
|
||
|
||
// 支持 ~ 作为用户目录(主要用于开发/测试环境)
|
||
if (path.StartsWith("~", StringComparison.Ordinal))
|
||
{
|
||
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||
var tail = path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||
path = Path.Combine(home, tail);
|
||
}
|
||
|
||
// 仅当不是绝对路径时,才基于程序目录做相对路径拼接
|
||
if (!Path.IsPathRooted(path))
|
||
{
|
||
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
|
||
}
|
||
return Path.GetFullPath(path);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 定时器回调:避免重入,统一调度导入任务
|
||
/// </summary>
|
||
private async Task OnTimerElapsedAsync()
|
||
{
|
||
if (_isRunning) return;
|
||
_isRunning = true;
|
||
try
|
||
{
|
||
await CheckAndImportAsync().ConfigureAwait(false);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"Excel 导入定时任务异常: {ex}");
|
||
}
|
||
finally
|
||
{
|
||
_isRunning = false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对外公开的手动触发方法,方便调试与单元测试
|
||
/// </summary>
|
||
public Task TriggerImportOnceAsync()
|
||
{
|
||
return CheckAndImportAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扫描源目录,按文件执行导入
|
||
/// </summary>
|
||
private async Task CheckAndImportAsync()
|
||
{
|
||
if (!Directory.Exists(_sourceDirectory))
|
||
{
|
||
_log.Warn($"Excel 导入目录不存在: {_sourceDirectory}");
|
||
return;
|
||
}
|
||
|
||
string[] files;
|
||
try
|
||
{
|
||
files = Directory.GetFiles(_sourceDirectory, "*.xlsx", SearchOption.TopDirectoryOnly);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"扫描 Excel 导入目录失败: dir={_sourceDirectory}, ex={ex.Message}");
|
||
return;
|
||
}
|
||
|
||
if (files.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 按文件名排序,确保按时间顺序处理
|
||
foreach (var filePath in files.OrderBy(f => Path.GetFileName(f)))
|
||
{
|
||
try
|
||
{
|
||
await ImportSingleFileAsync(filePath).ConfigureAwait(false);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"导入 Excel 文件失败: {filePath}, ex={ex}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导入单个 Excel 文件:按 Sheet 写入各表、记录日志并移动文件
|
||
/// </summary>
|
||
private async Task ImportSingleFileAsync(string filePath)
|
||
{
|
||
var fileName = Path.GetFileName(filePath);
|
||
if (string.IsNullOrWhiteSpace(fileName)) return;
|
||
|
||
// 若已存在成功记录,则不再重复导入
|
||
var alreadySuccess = await _fsql.Select<FileImportLog>()
|
||
.Where(x => x.FileName == fileName && x.Status == "Success")
|
||
.AnyAsync().ConfigureAwait(false);
|
||
if (alreadySuccess)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var log = new FileImportLog
|
||
{
|
||
FileName = fileName,
|
||
SourcePath = filePath,
|
||
StartTime = DateTime.Now,
|
||
Status = "Running"
|
||
};
|
||
|
||
var sheetStats = new Dictionary<string, int>();
|
||
|
||
try
|
||
{
|
||
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||
{
|
||
IWorkbook workbook = new XSSFWorkbook(fs);
|
||
var formatter = new DataFormatter();
|
||
|
||
sheetStats["FactoryInbound"] = ImportFactoryInbound(workbook, formatter);
|
||
sheetStats["FactoryMaterialWithdrawal"] = ImportFactoryMaterialWithdrawal(workbook, formatter);
|
||
sheetStats["FactoryInventoryTransaction"] = ImportFactoryInventoryTransaction(workbook, formatter);
|
||
sheetStats["FactoryProductionRecord"] = ImportFactoryProductionRecord(workbook, formatter);
|
||
sheetStats["FactoryOutbound"] = ImportFactoryOutbound(workbook, formatter);
|
||
sheetStats["OEMInbound"] = ImportOEMInbound(workbook, formatter);
|
||
sheetStats["OEMOutbound"] = ImportOEMOutbound(workbook, formatter);
|
||
sheetStats["OEMInventoryTransaction"] = ImportOEMInventoryTransaction(workbook, formatter);
|
||
sheetStats["OEMRawUsageInfo"] = ImportOEMRawUsageInfo(workbook, formatter);
|
||
}
|
||
|
||
// 构造统计摘要
|
||
log.SheetRowStats = string.Join(";", sheetStats.Select(kv => $"{kv.Key}={kv.Value}"));
|
||
|
||
// 移动文件到归档目录
|
||
var archivePath = Path.Combine(_archiveDirectory, fileName);
|
||
try
|
||
{
|
||
if (File.Exists(archivePath))
|
||
{
|
||
var newName = $"{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now:HHmmss}{Path.GetExtension(fileName)}";
|
||
archivePath = Path.Combine(_archiveDirectory, newName);
|
||
}
|
||
|
||
File.Move(filePath, archivePath);
|
||
log.ArchivePath = archivePath;
|
||
}
|
||
catch (Exception moveEx)
|
||
{
|
||
log.ArchivePath = archivePath;
|
||
_log.Error($"移动 Excel 文件到归档目录失败: src={filePath}, dest={archivePath}, ex={moveEx.Message}");
|
||
// 视为部分成功
|
||
}
|
||
|
||
log.Status = "Success";
|
||
log.Message = "OK";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
log.Status = "Failed";
|
||
log.Message = ex.Message;
|
||
|
||
if (sheetStats.Count > 0 && string.IsNullOrEmpty(log.SheetRowStats))
|
||
{
|
||
log.SheetRowStats = string.Join(";", sheetStats.Select(kv => $"{kv.Key}={kv.Value}"));
|
||
}
|
||
|
||
_log.Error($"导入 Excel 文件过程中出现异常: {filePath}, ex={ex}");
|
||
}
|
||
finally
|
||
{
|
||
log.EndTime = DateTime.Now;
|
||
try
|
||
{
|
||
await _fsql.Insert(log).ExecuteAffrowsAsync().ConfigureAwait(false);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_log.Error($"写入 FileImportLog 失败: file={fileName}, ex={ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
#region 各 Sheet 导入实现
|
||
|
||
private static bool IsRowEmpty(IRow? row, DataFormatter formatter)
|
||
{
|
||
if (row == null) return true;
|
||
for (int i = row.FirstCellNum; i < row.LastCellNum; i++)
|
||
{
|
||
var cell = row.GetCell(i);
|
||
if (cell != null && !string.IsNullOrWhiteSpace(formatter.FormatCellValue(cell)))
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
private static string GetCellString(IRow row, int columnIndex, DataFormatter formatter)
|
||
{
|
||
var cell = row.GetCell(columnIndex);
|
||
return cell == null ? string.Empty : formatter.FormatCellValue(cell).Trim();
|
||
}
|
||
|
||
private int ImportFactoryInbound(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("工厂-入库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<FactoryInbound>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new FactoryInbound
|
||
{
|
||
Origin = GetCellString(row, 0, formatter),
|
||
RawCode = GetCellString(row, 1, formatter),
|
||
RawName = GetCellString(row, 2, formatter),
|
||
Weight = GetCellString(row, 3, formatter),
|
||
LoginDate = GetCellString(row, 4, formatter),
|
||
LoginTime = GetCellString(row, 5, formatter),
|
||
LoginDateTime = GetCellString(row, 6, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.Origin, entity.RawCode, entity.RawName, entity.Weight, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportFactoryMaterialWithdrawal(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("工厂-领料");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<FactoryMaterialWithdrawal>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new FactoryMaterialWithdrawal
|
||
{
|
||
Origin = GetCellString(row, 0, formatter),
|
||
RawCode = GetCellString(row, 1, formatter),
|
||
RawName = GetCellString(row, 2, formatter),
|
||
Weight = GetCellString(row, 3, formatter),
|
||
LoginDate = GetCellString(row, 4, formatter),
|
||
LoginTime = GetCellString(row, 5, formatter),
|
||
LoginDateTime = GetCellString(row, 6, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.Origin, entity.RawCode, entity.RawName, entity.Weight, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportFactoryInventoryTransaction(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("工厂-出入库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<FactoryInventoryTransaction>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new FactoryInventoryTransaction
|
||
{
|
||
InTime = GetCellString(row, 0, formatter),
|
||
OutTime = GetCellString(row, 1, formatter),
|
||
Origin = GetCellString(row, 2, formatter),
|
||
RawCode = GetCellString(row, 3, formatter),
|
||
RawName = GetCellString(row, 4, formatter),
|
||
TotalInWeightKg = GetCellString(row, 5, formatter),
|
||
TotalOutWeightKg = GetCellString(row, 6, formatter),
|
||
RemainWeightKg = GetCellString(row, 7, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.InTime, entity.OutTime, entity.Origin, entity.RawCode, entity.RawName, entity.TotalInWeightKg, entity.TotalOutWeightKg, entity.RemainWeightKg))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportFactoryProductionRecord(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("工厂-原料生产信息");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<FactoryProductionRecord>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new FactoryProductionRecord
|
||
{
|
||
RawCode = GetCellString(row, 0, formatter),
|
||
RawName = GetCellString(row, 1, formatter),
|
||
Origin = GetCellString(row, 2, formatter),
|
||
InBagCode = GetCellString(row, 3, formatter),
|
||
BoxCode = GetCellString(row, 4, formatter),
|
||
Batch = GetCellString(row, 5, formatter),
|
||
ShelfLife = GetCellString(row, 6, formatter),
|
||
Weight = GetCellString(row, 7, formatter),
|
||
DeliveryDate = GetCellString(row, 8, formatter),
|
||
RemainWeight = GetCellString(row, 9, formatter),
|
||
StockWeight = GetCellString(row, 10, formatter),
|
||
WeightTime = GetCellString(row, 11, formatter),
|
||
OpUser = GetCellString(row, 12, formatter),
|
||
CheckUser = GetCellString(row, 13, formatter),
|
||
BoxScanTime = GetCellString(row, 14, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.RawCode, entity.RawName, entity.Origin, entity.InBagCode, entity.BoxCode, entity.Batch,
|
||
entity.ShelfLife, entity.Weight, entity.DeliveryDate, entity.RemainWeight, entity.StockWeight,
|
||
entity.WeightTime, entity.OpUser, entity.CheckUser, entity.BoxScanTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportFactoryOutbound(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("工厂-成品出库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<FactoryOutbound>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new FactoryOutbound
|
||
{
|
||
Batch = GetCellString(row, 0, formatter),
|
||
Weight = GetCellString(row, 1, formatter),
|
||
ShelfLife = GetCellString(row, 2, formatter),
|
||
Origin = GetCellString(row, 3, formatter),
|
||
RawCode = GetCellString(row, 4, formatter),
|
||
RawName = GetCellString(row, 5, formatter),
|
||
SequenceNo = GetCellString(row, 6, formatter),
|
||
LoginDate = GetCellString(row, 7, formatter),
|
||
LoginTime = GetCellString(row, 8, formatter),
|
||
LoginDateTime = GetCellString(row, 9, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportOEMInbound(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("OEM-入库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<OEMInbound>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new OEMInbound
|
||
{
|
||
Batch = GetCellString(row, 0, formatter),
|
||
Weight = GetCellString(row, 1, formatter),
|
||
ShelfLife = GetCellString(row, 2, formatter),
|
||
Origin = GetCellString(row, 3, formatter),
|
||
RawCode = GetCellString(row, 4, formatter),
|
||
RawName = GetCellString(row, 5, formatter),
|
||
SequenceNo = GetCellString(row, 6, formatter),
|
||
LoginDate = GetCellString(row, 7, formatter),
|
||
LoginTime = GetCellString(row, 8, formatter),
|
||
LoginDateTime = GetCellString(row, 9, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportOEMOutbound(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("OEM-出库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<OEMOutbound>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new OEMOutbound
|
||
{
|
||
Batch = GetCellString(row, 0, formatter),
|
||
Weight = GetCellString(row, 1, formatter),
|
||
ShelfLife = GetCellString(row, 2, formatter),
|
||
Origin = GetCellString(row, 3, formatter),
|
||
RawCode = GetCellString(row, 4, formatter),
|
||
RawName = GetCellString(row, 5, formatter),
|
||
SequenceNo = GetCellString(row, 6, formatter),
|
||
LoginDate = GetCellString(row, 7, formatter),
|
||
LoginTime = GetCellString(row, 8, formatter),
|
||
LoginDateTime = GetCellString(row, 9, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.Batch, entity.Weight, entity.ShelfLife, entity.Origin, entity.RawCode, entity.RawName,
|
||
entity.SequenceNo, entity.LoginDate, entity.LoginTime, entity.LoginDateTime))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportOEMInventoryTransaction(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("OEM-出入库");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<OEMInventoryTransaction>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new OEMInventoryTransaction
|
||
{
|
||
InTime = GetCellString(row, 0, formatter),
|
||
OutTime = GetCellString(row, 1, formatter),
|
||
Origin = GetCellString(row, 2, formatter),
|
||
RawCode = GetCellString(row, 3, formatter),
|
||
RawName = GetCellString(row, 4, formatter),
|
||
TotalInCase = GetCellString(row, 5, formatter),
|
||
TotalOutCase = GetCellString(row, 6, formatter),
|
||
RemainCase = GetCellString(row, 7, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.InTime, entity.OutTime, entity.Origin, entity.RawCode, entity.RawName,
|
||
entity.TotalInCase, entity.TotalOutCase, entity.RemainCase))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private int ImportOEMRawUsageInfo(IWorkbook workbook, DataFormatter formatter)
|
||
{
|
||
var sheet = workbook.GetSheet("OEM-原料使用信息");
|
||
if (sheet == null) return 0;
|
||
|
||
var list = new List<OEMRawUsageInfo>();
|
||
for (int i = 1; i <= sheet.LastRowNum; i++)
|
||
{
|
||
var row = sheet.GetRow(i);
|
||
if (IsRowEmpty(row, formatter)) continue;
|
||
|
||
var entity = new OEMRawUsageInfo
|
||
{
|
||
RawUseTime = GetCellString(row, 0, formatter),
|
||
InBagCode = GetCellString(row, 1, formatter),
|
||
Origin = GetCellString(row, 2, formatter),
|
||
RawName = GetCellString(row, 3, formatter),
|
||
RawCode = GetCellString(row, 4, formatter),
|
||
VideoUrl = GetCellString(row, 5, formatter)
|
||
};
|
||
|
||
if (IsAllEmpty(entity.RawUseTime, entity.InBagCode, entity.Origin, entity.RawName, entity.RawCode, entity.VideoUrl))
|
||
continue;
|
||
|
||
list.Add(entity);
|
||
}
|
||
|
||
if (list.Count > 0)
|
||
{
|
||
_fsql.Insert(list).ExecuteAffrows();
|
||
}
|
||
return list.Count;
|
||
}
|
||
|
||
private static bool IsAllEmpty(params string?[] values)
|
||
{
|
||
if (values == null || values.Length == 0) return true;
|
||
foreach (var v in values)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(v)) return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 释放定时器等资源
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
if (_disposed) return;
|
||
_disposed = true;
|
||
|
||
try
|
||
{
|
||
_timer?.Stop();
|
||
_timer?.Dispose();
|
||
}
|
||
catch
|
||
{
|
||
// 忽略定时器释放异常
|
||
}
|
||
}
|
||
}
|
||
}
|