private Metadata(IEnumerable <NE> exprsHdr, IEnumerable <NE> exprsRow, IEnumerable <NE> exprsRes, Generator.Ctx parentCtx) { var sb = new StringBuilder(); FixSheetExpr = Expr.RecursiveModifier(FixSheetImpl); FixRowExpr = Expr.RecursiveModifier(FixRowImpl); #region generate header code ctxHdr = new Generator.Ctx(parentCtx); ctxHdr.CreateValue(HdrCellsRef.name, Generator.LazyDummy); ctxHdr.CreateValue(PrevValsRef.name, Generator.LazyDummy); foreach (var p in exprsHdr) { FCurrName = p.name; var expr = FixSheetExpr(p.expr); var val = Generator.Generate(expr, ctxHdr); ctxHdr.CreateValue(p.name, val); if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } sb.AppendLine($"{p.name} = {expr}"); } sb.AppendLine(); RequiredInHdr(sSourceKey); RequiredInHdr(sSourceName); RequiredInHdr(sCondition); RequiredInHdr(sFirstDataRowNum); { if (ctxHdr.name2ndx.TryGetValue(sFileContentKind, out int i)) { FileContentKind = Convert.ToString(ctxHdr.GetConstant(sFileContentKind)); } else { FileContentKind = "XLSX"; } } { if (ctxHdr.name2ndx.TryGetValue(sFileNameExtension, out int i)) { var val = ctxHdr.GetConstant(sFileNameExtension); FileNameExtension = Utils.AsIList(val).Cast <object>().Select(Convert.ToString).ToArray(); } else { FileNameExtension = new string[] { "xls", "xlsx", "xlsm" } }; } #endregion #region generate row code ctxRow = new Generator.Ctx(ctxHdr); ctxRow.CreateValue(sDataKey, Generator.LazyDummy); // [0] - iKey ctxRow.CreateValue(sDataSubkey, Generator.LazyDummy); // [1] - iSubkey ctxRow.CreateValue(CellValsRef.name, Generator.LazyDummy); // [2] - iRowVals foreach (var p in exprsRow) { string name; if (p.name.StartsWith("~")) { // calculated name name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name; } else { name = p.name; } FCurrName = name; int i = ctxRow.GetOrCreateIndexOf(name); var expr = FixRowExpr(p.expr); var val = Generator.Generate(expr, ctxRow); ctxRow.values[i] = val; if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } sb.AppendLine($"{name} = {expr}"); } RequiredInRow(sDataKey); RequiredInRow(sDataSubkey); ctxRow.values[iRowVals] = null; ctxRow.CheckUndefinedValues(); #endregion #region generate res code if (exprsRes != null) { // copy all code from row to res ctxRes = new Generator.Ctx(ctxHdr); foreach (var p in ctxRow.name2ndx.OrderBy(p => p.Value)) { ctxRes.values[ctxRes.CreateValue(p.Key)] = ctxRow.values[p.Value]; } foreach (var p in exprsRes) { string name; if (p.name.StartsWith("~")) { // calculated name name = OPs.TryAsString(Parser.ParseToExpr(p.name.Substring(1)), ctxHdr) ?? p.name; } else { name = p.name; } FCurrName = name; int i = ctxRes.GetOrCreateIndexOf(name); var expr = FixRowExpr(p.expr); var val = Generator.Generate(expr, ctxRes); ctxRes.values[i] = val; if (OPs.KindOf(val) == ValueKind.Const) { expr = new ConstExpr(val); } } ctxRes.values[iRowVals] = null; ctxRes.CheckUndefinedValues(); } #endregion ctxHdr[HdrCellsRef.name] = null; ctxHdr[PrevValsRef.name] = null; ctxHdr.CheckUndefinedValues(); FCodeText = sb.ToString(); if (iHdrMinUsedRow > iHdrMaxUsedRow) { iHdrMinUsedRow = iHdrMaxUsedRow; } }