luban/src/LubanAssistant/ExcelUtil.cs

221 lines
7.8 KiB
C#

using Luban.Job.Cfg.DataExporters;
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.DataSources.Excel;
using Luban.Job.Cfg.DataVisitors;
using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.Utils;
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace LubanAssistant
{
static class ExcelUtil
{
public static Dictionary<string, string> ParseMetaAttrs(Worksheet sheet)
{
Range metaRow = sheet.Rows[1];
if (metaRow.Cells[1, 1].Text.ToString() != "##")
{
throw new Exception("A1 should be ##");
}
var metaAttrs = new Dictionary<string, string>();
for (int i = 2, n = sheet.UsedRange.Columns.Count; i <= n; i++)
{
Range cell = metaRow.Cells[1, i];
string value = cell.Value?.ToString();
if (!string.IsNullOrWhiteSpace(value))
{
var attrs = value.Split('=');
if (attrs.Length != 2)
{
throw new Exception($"invalid meta attr:{value}");
}
metaAttrs.Add(attrs[0], attrs[1]);
}
}
return metaAttrs;
}
public static TitleInfo ParseTitles(Worksheet sheet)
{
int titleRows = 1;
Range c1 = sheet.Cells[2, 1];
if (c1.MergeCells)
{
titleRows = c1.MergeArea.Count;
}
var rootTile = new Title()
{
FromIndex = 2,
ToIndex = sheet.UsedRange.Columns.Count,
Name = "__root__",
Root = true,
};
ParseSubTitle(sheet, 2, titleRows + 1, rootTile);
return new TitleInfo(rootTile, titleRows);
}
private static void ParseSubTitle(Worksheet sheet, int rowIndex, int maxRowIndex, Title title)
{
Range row = sheet.Rows[rowIndex];
for (int i = title.FromIndex; i <= title.ToIndex; i++)
{
Range subTitleRange = row.Cells[1, i];
string subTitleValue = subTitleRange.Value?.ToString();
if (string.IsNullOrWhiteSpace(subTitleValue))
{
continue;
}
var attrs = subTitleValue.Split('&');
string subTitleName = attrs[0];
string sep = "";
foreach (var attrPair in attrs.Skip(1))
{
var pairs = attrPair.Split('=');
if (pairs.Length != 2)
{
throw new Exception($"invalid title: {subTitleValue}");
}
switch (pairs[0])
{
case "sep":
{
sep = pairs[1];
break;
}
default:
{
throw new Exception($"invalid title: {subTitleValue}");
}
}
}
if (title.SubTitles.ContainsKey(subTitleName))
{
throw new Exception($"title:{subTitleName} 重复");
}
var newSubTitle = new Title()
{
Name = subTitleName,
FromIndex = i,
ToIndex = i,
};
if (!string.IsNullOrWhiteSpace(sep))
{
newSubTitle.Sep = sep;
}
if (subTitleRange.MergeCells)
{
newSubTitle.ToIndex = i + subTitleRange.MergeArea.Count - 1;
}
else
{
newSubTitle.ToIndex = i;
}
title.SubTitles.Add(subTitleName, newSubTitle);
}
title.SubTitleList.AddRange(title.SubTitles.Values);
if (rowIndex < maxRowIndex)
{
foreach (var subTitle in title.SubTitleList)
{
ParseSubTitle(sheet, rowIndex + 1, maxRowIndex, subTitle);
}
}
}
public static void FillRecords(Worksheet sheet, Dictionary<string, string> metaAttrs, TitleInfo title, TableDataInfo tableDataInfo)
{
int titleRowNum = 3;
if (metaAttrs.TryGetValue("title_rows", out var titleRowsStr) && !int.TryParse(titleRowsStr, out titleRowNum))
{
throw new Exception($"meta 属性 title_rows 不合法");
}
if (titleRowNum < title.RowNum)
{
throw new Exception($"meta 属性title_rows不能比字段名行的行数小");
}
int usedRowNum = sheet.UsedRange.Rows.Count;
if (usedRowNum > titleRowNum + 1)
{
Range allDataRange = sheet.Range[$"A{titleRowNum + 2},A{usedRowNum}"].EntireRow;
allDataRange.ClearContents();
}
int nextRowIndex = titleRowNum + 2;
foreach (var rec in tableDataInfo.MainRecords)
{
var fillVisitor = new FillSheetVisitor(sheet, nextRowIndex);
//FillRecord(sheet, ref nextRowIndex, title.RootTitle, rec);
nextRowIndex += rec.Data.Apply(fillVisitor, title.RootTitle);
}
}
public static List<Record> LoadRecordsInRange(DefTable table, Worksheet sheet, Title title, Range toSaveRecordRows)
{
var recs = new List<Record>();
foreach (Range row in toSaveRecordRows)
{
bool allEmpty = true;
for (int i = title.FromIndex; i <= title.ToIndex; i++)
{
if (!string.IsNullOrEmpty((row.Cells[1, i] as Range).Value?.ToString()))
{
allEmpty = false;
break;
}
}
if (allEmpty)
{
continue;
}
string tags = (row.Cells[1, 1] as Range).Value?.ToString();
recs.Add(new Record(
(DBean)table.ValueTType.Apply(new SheetDataCreator(sheet, row.Row, table.Assembly), title, null),
"",
DataUtil.ParseTags(tags)));
}
return recs;
}
public static void SaveRecords(string inputDataDir, DefTable table, List<Record> records)
{
var recordOutputDir = Path.Combine(inputDataDir, table.InputFiles[0]);
string index = table.IndexField.Name;
foreach (var r in records)
{
var ss = new MemoryStream();
var jsonWriter = new Utf8JsonWriter(ss, new JsonWriterOptions()
{
Indented = true,
SkipValidation = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),
});
RawJsonExportor.Ins.Accept(r.Data, jsonWriter);
jsonWriter.Flush();
var key = r.Data.GetField(index);
var fileName = $"{key.Apply(ToStringVisitor.Ins)}.json";
File.WriteAllBytes(Path.Combine(recordOutputDir, fileName), DataUtil.StreamToBytes(ss));
}
}
//public static void FillRecord(Worksheet sheet, ref int nextRowIndex, Title title, Record record)
//{
// nextRowIndex += FillField(sheet, nextRowIndex, title, record.Data);
//}
}
}