Exemple #1
0
            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;
                }
            }
Exemple #2
0
            Expr SpecFuncs(CallExpr ce)
            {
                Expr src, ndx;
                bool forPrev = false, forCell = false;
                int  nMinArgs = 1;

                switch (ce.funcName)
                {
                case "PREVCELL":
                    forCell = true; forPrev = true; break;

                case "PREV":
                    nMinArgs = 0; forPrev = true; break;

                case "INDIRECT":
                    forCell = true; break;

                case nameof(FuncDefs_Xlsx.COLUMN):
                    // avoid COLUMN(args) fixing
                    return(new CallExpr(nameof(FuncDefs_Xlsx.COLUMN), ce.args));

                default:
                    return(ce);
                }
                if (ce.args.Count < nMinArgs)
                {
                    return(ce);
                }

                Expr   arg;
                string name;

                if (ce.args.Count == 0)
                {
                    arg  = null;
                    name = FCurrName;
                }
                else
                {
                    arg = ce.args[0];
                    if (arg.nodeType == ExprType.Reference)
                    {
                        name = ((ReferenceExpr)arg).name;
                        if (IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                        {
                            forCell = true;
                        }
                        else
                        {
                            name = OPs.TryAsString(arg, ctxRow) ?? name;
                        }
                    }
                    else
                    {
                        arg  = FixRowExpr(arg);
                        name = OPs.TryAsName(arg, ctxRow);
                    }
                }

                if (name == null)
                {
                    var undefs = string.Join(", ", ctxHdr.NamesOfUndefinedValues().Concat(ctxRow.NamesOfUndefinedValues()));
                    throw new Source.Exception($"Constant expected as value of {ce.args[0]}={arg} // ??? {undefs}");
                }

                if (forCell || IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                {
                    if (forPrev)
                    {
                        src = new IndexExpr(PrevValsRef, new ConstExpr(ctxRow.IndexOf(CellValsRef.name)));
                    }
                    else
                    {
                        var re1 = new ReferenceExpr(name);
                        var re2 = FixHdrCellRef(re1);
                        if (re2 != re1)
                        {
                            // ref to header cell
                            return(re2);
                        }
                        else
                        {
                            // ref to row cell
                            src = CellValsRef;
                        }
                    }
                    ndx = new ConstExpr(name);
                }
                else
                {
                    int i = ctxRow.IndexOf(name);
                    if (i < 0 || Generator.Ctx.ctxDepthStep <= i)
                    {
                        throw new Source.Exception($"Value named '{name}' not found in row context");
                    }
                    src = PrevValsRef;
                    ndx = new ConstExpr(i);
                }
                return(new IndexExpr(src, ndx));
            }