private bool FindDestNameInLocalNames(int DestSheet, TNameToken aName, TNameRecord Name) { for (int i = SheetInfo.DestNames.Count - 1; i >= 0; i--) { TNameRecord NewName = SheetInfo.DestNames[i]; if (NewName.RangeSheet == DestSheet && String.Equals(NewName.Name, Name.Name, StringComparison.CurrentCultureIgnoreCase)) { aName.NameIndex = i + 1; return(true); } } return(false); }
private void CheckFutureFunction(TParsedTokenListBuilder TokenBuilder, ref int np, TNameRecordList Names, ref TCellFunctionData fd2, TTokenOffset TokenOffset, ref bool HasAggregate) { //We need to recursively read parameters in back order to find out the name, which is stored as far as possible from the function :( TParsedTokenList ParsedList = TokenBuilder.ToParsedTokenList(); ParsedList.ResetPositionToLast(); for (int i = 0; i < np; i++) //np is +1. But we will move below the name, then inc 1, so we know there isn't a "neutral" token like parent or memarea, intead of the real thing. { ParsedList.Flush(); } ParsedList.MoveBack(); TNameToken bp = ParsedList.ForwardPop() as TNameToken; if (bp is TNameXToken) { return; //This name isn't an internal 2007 name. } if (bp == null) { return; } if (bp.NameIndex <= 0 || bp.NameIndex > Names.Count) { return; } string FunctionName = Names[bp.NameIndex - 1].Name; if (FunctionName.StartsWith("_xlfn.", StringComparison.InvariantCultureIgnoreCase)) { TCellFunctionData fn = TXlsFunction.GetData(FunctionName.Substring("_xlfn.".Length)); if (fn != null) { if (fn.Index == (int)TFutureFunctions.Aggregate) { HasAggregate = true; } fd2 = fn; int tPos = ParsedList.SavePosition(); TokenBuilder.RemoveAt(tPos); TokenOffset.RemoveToken(tPos); np--; } } }
private static void FindReferences(TNameToken r, TDeletedRanges DeletedRanges) { int NameId = r.NameIndex - 1; if (NameId < 0 || NameId >= DeletedRanges.Count) { return; } if (DeletedRanges.Referenced(NameId)) { return; //Avoid infinite loop if one range refers to other and vice versa. } DeletedRanges.Reference(NameId); //We also need to recursively find all other names referenced by this name. TNameRecord Name = DeletedRanges.Names[NameId]; Name.UpdateDeletedRanges(DeletedRanges); }
internal static void UpdateDeletedRanges(TParsedTokenList Data, TDeletedRanges DeletedRanges) { Data.ResetPositionToLast(); while (!Data.Bof()) { TBaseParsedToken tk = Data.LightPop(); TBaseFunctionToken ft = tk as TBaseFunctionToken; if (ft != null) { //we need to ensure we don't delete the used _xlfn. ranges. Used def fn don't need to check, because they use the name in the tokenlist. if (ft.GetFunctionData().FutureInXls) { int NameId = DeletedRanges.Names.GetNamePos(-1, ft.GetFunctionData().FutureName); if (NameId >= 0) { DeletedRanges.Reference(NameId); //No need for recursion here, this name can't use anything else. Also, we don't need to update refs to this range. } } continue; } TNameToken r = tk as TNameToken; //this includes namex if (r == null) { continue; } if (r.GetBaseId == ptg.NameX && !DeletedRanges.References.IsLocalSheet(r.ExternSheet)) { return; //This name does not point to a name in the NAME table. } if (DeletedRanges.Update) { UpdateRange(r, DeletedRanges); } else { FindReferences(r, DeletedRanges); } } }
protected override void DoName(TNameToken aName) { if (SheetInfo.SourceReferences != null && SheetInfo.SourceNames != null) { TNameRecord Name = SheetInfo.SourceNames[aName.NameIndex - 1]; int NameSheet = Name.RangeSheet; if (SheetInfo.SourceReferences != SheetInfo.DestReferences) //Copy the names to the new file. { //Copy the name to the new reference. if (!FindDestNameInLocalNames(SheetInfo.DestFormulaSheet, aName, Name)) //Search in local names { // If not found in local names, we will add a new one, even if it is defined as global. So if // we copy to sheets with each one a ref to a name in the sheet, both reference different things. //This would cause infinite recursion if the name is "A = A" (or A=B and B=A) //TNameRecord NewName = Name.CopyTo(SheetInfo.DestFormulaSheet, CopyRowOffset, CopyColOffset, SheetInfo); int DestSheet = SheetInfo.DestFormulaSheet; if (Name.RangeSheet < 0 && (Name.IsAddin || Name.Data.Count == 0)) { DestSheet = Name.RangeSheet; //Macros and stuff should be copied in the global sheet. } TNameRecord NewName = TNameRecord.CreateTempName(Name.Name, DestSheet); int NamePos; bool Added = SheetInfo.DestNames.AddNameIfNotExists(NewName, out NamePos); if (Added) { SheetInfo.DestNames[NamePos] = Name.CopyTo(DestSheet, CopyRowOffset, CopyColOffset, SheetInfo); } aName.NameIndex = NamePos + 1;// + 1; } } else if (InsertingSheet && (NameSheet == SheetInfo.SourceFormulaSheet || NameSheet < 0)) { FindDestNameInLocalNames(SheetInfo.InsSheet, aName, Name); //If not found do nothing, it is a ref to a global name in the same sheet, so we just keep it. } } }
private static void UpdateRange(TNameToken r, TDeletedRanges DeletedRanges) { int NameId = r.NameIndex - 1; if (NameId < 0 || NameId >= DeletedRanges.Count) { return; } Debug.Assert(DeletedRanges.Referenced(NameId), "Can't delete ranges that have references. Excel does not do it, and doesn't provide a way to create invalid references for ranges."); int ofs = DeletedRanges.Offset(NameId); if (ofs == 0) { return; } NameId -= ofs; Debug.Assert(NameId >= 0); r.NameIndex = NameId + 1; }
protected override void DoName(TNameToken aName) { //No changes when moving things. }
protected abstract void DoName(TNameToken aName);