基线:全量源码首提(D1 版本控制落地,含第一轮优化 B1-B4/A1/A4/缩放修复)
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""甲方报表 FillDetailSheet 重写:DOM 组装(上万行节点树+OuterXml 双份字符串→32位OOM)
|
||||
改为字符串模板替换法:提取模板行字符串→逐行换号/替换单元格→拼接输出。零 DOM、单份字符串。"""
|
||||
import io
|
||||
import re
|
||||
|
||||
P = r"C:\Users\099978\Documents\SharpDevelop Projects\成套报价软件\成套报价软件\xiangmu\甲方报表.cs"
|
||||
s = io.open(P, encoding="utf-8-sig").read()
|
||||
|
||||
start_anchor = " private void FillDetailSheet(Dictionary<string, byte[]> entries, string sheetKey,"
|
||||
end_anchor = " entries[sheetKey] = System.Text.Encoding.UTF8.GetBytes(doc.OuterXml);\n }"
|
||||
|
||||
i0 = s.find(start_anchor)
|
||||
assert i0 > 0, "起点未找到"
|
||||
i1 = s.find(end_anchor, i0)
|
||||
assert i1 > 0, "终点未找到"
|
||||
i1 += len(end_anchor)
|
||||
|
||||
NEW = ''' // ============ 明细表:字符串模板替换法(零 DOM——上万像素级 DOM+OuterXml 双份字符串会 OOM) ============
|
||||
|
||||
/// <summary>行字符串:更新行号与全部单元格引用(r="列行号")。</summary>
|
||||
private static string 行换号(string rowXml, int rowNum)
|
||||
{
|
||||
rowXml = System.Text.RegularExpressions.Regex.Replace(rowXml, "<row r=\\"\\\\d+\\"", "<row r=\\"" + rowNum + "\\"");
|
||||
return System.Text.RegularExpressions.Regex.Replace(rowXml, "r=\\"([A-Z]+)\\\\d+\\"", "r=\\"$1" + rowNum + "\\"");
|
||||
}
|
||||
|
||||
/// <summary>行字符串:设置某列单元格内容(innerXml=单元格内部 XML;tAttr=类型属性,null=移除 t)。</summary>
|
||||
private static string 行设单元格(string rowXml, string col, int rowNum, string innerXml, string tAttr)
|
||||
{
|
||||
string r = col + rowNum;
|
||||
var m = System.Text.RegularExpressions.Regex.Match(rowXml, "<c r=\\"" + r + "\\"([^>]*?)(?:/>|>.*?</c>)");
|
||||
if (!m.Success) return rowXml;
|
||||
string attrs = m.Groups[1].Value;
|
||||
attrs = System.Text.RegularExpressions.Regex.Replace(attrs, "\\\\s*t=\\"[^\\"]*\\"", "");
|
||||
if (!string.IsNullOrEmpty(tAttr)) attrs += " t=\\"" + tAttr + "\\"";
|
||||
return rowXml.Substring(0, m.Index) + "<c r=\\"" + r + "\\"" + attrs + ">" + innerXml + "</c>" + rowXml.Substring(m.Index + m.Length);
|
||||
}
|
||||
|
||||
private static string 行设文本(string rowXml, string col, int rowNum, string text)
|
||||
{ return 行设单元格(rowXml, col, rowNum, "<v>" + XmlEscape(text) + "</v>", "str"); }
|
||||
|
||||
private static string 行设数值(string rowXml, string col, int rowNum, decimal v)
|
||||
{ return 行设单元格(rowXml, col, rowNum, "<v>" + v.ToString(System.Globalization.CultureInfo.InvariantCulture) + "</v>", null); }
|
||||
|
||||
private static string 行设公式(string rowXml, string col, int rowNum, string formula)
|
||||
{ return 行设单元格(rowXml, col, rowNum, "<f>" + XmlEscape(formula) + "</f>", null); }
|
||||
|
||||
private void FillDetailSheet(Dictionary<string, byte[]> entries, string sheetKey,
|
||||
List<TuhaoData> tuhaoList, List<CabinetRowInfo> cabRowInfos, System.Text.StringBuilder dbgLog,
|
||||
bool useFormula)
|
||||
{
|
||||
string xml = System.Text.Encoding.UTF8.GetString(entries[sheetKey]);
|
||||
|
||||
// 提取全部行块,定位模板行 11~16 与头/尾(零 DOM)
|
||||
var 行匹配 = System.Text.RegularExpressions.Regex.Matches(
|
||||
xml, "<row r=\\"(\\\\d+)\\"[^>]*?(?:/>|>.*?</row>)");
|
||||
if (行匹配.Count == 0) return;
|
||||
|
||||
string[] tpl = new string[6];
|
||||
int bodyStart = -1, bodyEnd = -1;
|
||||
foreach (System.Text.RegularExpressions.Match m in 行匹配)
|
||||
{
|
||||
int rn = int.Parse(m.Groups[1].Value);
|
||||
if (rn >= 11 && rn <= 16)
|
||||
{
|
||||
tpl[rn - 11] = m.Value;
|
||||
if (bodyStart < 0) bodyStart = m.Index;
|
||||
bodyEnd = m.Index + m.Length;
|
||||
}
|
||||
}
|
||||
string tplPaperRow = tpl[0], tplCabRow = tpl[1], tplHeaderRow = tpl[2],
|
||||
tplElemRow = tpl[3], tplSingleRow = tpl[4], tplGrandRow = tpl[5];
|
||||
if (tplCabRow == null || tplElemRow == null) return;
|
||||
|
||||
string 头 = xml.Substring(0, bodyStart); // 行1~10
|
||||
string 尾 = xml.Substring(bodyEnd); // 行17(签名)及之后
|
||||
|
||||
var sb = new System.Text.StringBuilder();
|
||||
int rowNum = 11;
|
||||
decimal grandQty = 0, grandTotal = 0;
|
||||
int tuhaoIdx = 0;
|
||||
|
||||
foreach (var tuhao in tuhaoList)
|
||||
{
|
||||
string tuhaoName = !string.IsNullOrEmpty(tuhao.TuMing) ? tuhao.TuMing : tuhao.Tuhao;
|
||||
|
||||
// 图名行
|
||||
if (tplPaperRow != null)
|
||||
{
|
||||
string row = 行换号(tplPaperRow, rowNum);
|
||||
row = 行设文本(row, "A", rowNum, tuhaoName);
|
||||
sb.Append(row);
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 每个箱号: 柜号行 + 表头 + 元件行*N + 单台合计 + 总计
|
||||
int cabOrder = 0;
|
||||
foreach (var cab in tuhao.Cabinets)
|
||||
{
|
||||
cabOrder++;
|
||||
int cabRowNum = rowNum;
|
||||
|
||||
// 柜号行
|
||||
{
|
||||
string row = 行换号(tplCabRow, rowNum);
|
||||
row = 行设文本(row, "A", rowNum, (tuhaoIdx + 1) + "-" + cabOrder);
|
||||
row = 行设文本(row, "B", rowNum, "柜号:" + cab.CabinetNo);
|
||||
row = 行设文本(row, "D", rowNum, cab.Model);
|
||||
// ★ G列"名称:"= 箱名(进线柜/PT柜等);库里没有时退回图名(与旧版行为一致)
|
||||
string 名称值 = !string.IsNullOrEmpty(cab.BoxName) ? cab.BoxName : tuhaoName;
|
||||
row = 行设文本(row, "G", rowNum, 名称值);
|
||||
row = 行设文本(row, "I", rowNum, cab.SpecName);
|
||||
sb.Append(row);
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 表头行
|
||||
if (tplHeaderRow != null)
|
||||
{
|
||||
sb.Append(行换号(tplHeaderRow, rowNum));
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 元件行(G列用 =E*F 公式)
|
||||
int elemStartRow = rowNum;
|
||||
if (cab.Elements.Count == 0)
|
||||
{
|
||||
sb.Append(行换号(tplElemRow, rowNum));
|
||||
rowNum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int elemOrder = 0;
|
||||
foreach (var elem in cab.Elements)
|
||||
{
|
||||
elemOrder++;
|
||||
string row = 行换号(tplElemRow, rowNum);
|
||||
row = 行设文本(row, "A", rowNum, elemOrder.ToString());
|
||||
row = 行设文本(row, "B", rowNum, elem.Name);
|
||||
row = 行设文本(row, "C", rowNum, elem.ShowSpecName);
|
||||
row = 行设文本(row, "D", rowNum, elem.Unit);
|
||||
row = 行设数值(row, "E", rowNum, SafeDec(elem.Count));
|
||||
row = 行设数值(row, "F", rowNum, elem.OfferUnitPrice);
|
||||
// G列: 公式 =E{行}*F{行} 或直接值
|
||||
if (useFormula)
|
||||
row = 行设公式(row, "G", rowNum, "E" + rowNum + "*F" + rowNum);
|
||||
else
|
||||
row = 行设数值(row, "G", rowNum, SafeDec(elem.Count) * elem.OfferUnitPrice);
|
||||
row = 行设文本(row, "H", rowNum, elem.FactName);
|
||||
row = 行设文本(row, "I", rowNum, elem.Remark);
|
||||
sb.Append(row);
|
||||
rowNum++;
|
||||
}
|
||||
}
|
||||
int elemEndRow = rowNum - 1;
|
||||
|
||||
// 单台合计行(G列用 =ROUND(SUM(G{起}:G{止}),0) 公式)
|
||||
int singleRowNum = rowNum;
|
||||
if (tplSingleRow != null)
|
||||
{
|
||||
string row = 行换号(tplSingleRow, rowNum);
|
||||
row = 行设文本(row, "B", rowNum, "单台合计");
|
||||
if (useFormula)
|
||||
row = 行设公式(row, "G", rowNum, "ROUND(SUM(G" + elemStartRow + ":G" + elemEndRow + "),0)");
|
||||
else
|
||||
{
|
||||
decimal elemSum = 0;
|
||||
foreach (var elem in cab.Elements) elemSum += SafeDec(elem.Count) * elem.OfferUnitPrice;
|
||||
row = 行设数值(row, "G", rowNum, elemSum);
|
||||
}
|
||||
sb.Append(row);
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 总计行(G列用 =G{单台合计}*E{总计} 公式)
|
||||
int grandRowNum = rowNum;
|
||||
if (tplGrandRow != null)
|
||||
{
|
||||
string row = 行换号(tplGrandRow, rowNum);
|
||||
row = 行设文本(row, "B", rowNum, "总计");
|
||||
row = 行设文本(row, "D", rowNum, "台");
|
||||
row = 行设数值(row, "E", rowNum, SafeDec(cab.Count));
|
||||
if (useFormula)
|
||||
row = 行设公式(row, "G", rowNum, "G" + singleRowNum + "*E" + rowNum);
|
||||
else
|
||||
{
|
||||
decimal elemSum = 0;
|
||||
foreach (var elem in cab.Elements) elemSum += SafeDec(elem.Count) * elem.OfferUnitPrice;
|
||||
row = 行设数值(row, "G", rowNum, elemSum * SafeDec(cab.Count));
|
||||
}
|
||||
sb.Append(row);
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// 记录行号供汇总表引用
|
||||
cabRowInfos.Add(new CabinetRowInfo
|
||||
{
|
||||
CabRow = cabRowNum,
|
||||
SingleTotalRow = singleRowNum,
|
||||
GrandRow = grandRowNum
|
||||
});
|
||||
|
||||
grandQty += SafeDec(cab.Count);
|
||||
grandTotal += cab.OfferTotalPrice;
|
||||
}
|
||||
tuhaoIdx++;
|
||||
}
|
||||
|
||||
entries[sheetKey] = System.Text.Encoding.UTF8.GetBytes(头 + sb.ToString() + 尾);
|
||||
}'''
|
||||
|
||||
s = s[:i0] + NEW + s[i1:]
|
||||
io.open(P, "w", encoding="utf-8-sig").write(s)
|
||||
print("FillDetailSheet 已重写为字符串模板法")
|
||||
Reference in New Issue
Block a user