Токены формул и пользовательские функции
HotXLS предоставляет принадлежащие вызывающему коду потоки токенов формул для безошибочного просмотра и защищённой обратной записи в обоих движках книг, а также иерархические реестры пользовательских функций для пользовательских вычислений
Модель токенов
TXLSFormulaTokenClass, TXLSFormulaTokenKindи TXLSFormulaTokenSource классифицируют каждый TXLSFormulaToken и фиксируют, получен ли он из разобранного текста, классических байтов BIFF или другого поддерживаемого источника
| TXLSFormulaToken | Kind, Opcode, BaseOpcode, TokenClass, RawBytes, TextValue, NumberValue, IntegerValue, ArgumentCount, FunctionIndex, ExternSheetIndex, Row1, Col1, Row2, Col2, Row1Relative, Col1Relative, Row2Relative, Col2Relative, ReferenceUsesOffsets, Supported, ArrayRows, ArrayCols, ArrayValueCountи ArrayValues |
| TXLSFormulaTokenStream | DecodeBiff, Clone, CloneSyntaxTree, BindContext, CanCompileFor, CanWriteBiffAt, ReplaceReference, Count, Items, Source, FormulaText, FullyDecodedи Rgce, RgbExtra, BiffWritable, and BiffVersion |
| TXLSCompiledFormula | CreateTokenStream возвращает принадлежащую вызывающему коду копию потока токенов скомпилированной формулы |
| TXLSFormula | ArrayFormulaMode, FormulaLocale, MaxRow, MaxCol, FuncNamebyPtg, FuncArgsCntByPtg, GetCompiled, GetCompiledPreservingUnknownNames, GetCompiledR1C1, GetTokenStream, GetTranslated, GetStoreData, GetStoreDataExt, CanStoreData, BindUserDefinedFunctions, GetTExpData, SetMode, IsKnownFunction, GetFunctionNamesи FunctionArgumentClass |
Каждый книжный движок компилирует и транслирует формулы через один общий экземпляр TXLSFormula: GetCompiled разбирает текст в стиле A1 в синтаксическое дерево, GetCompiledR1C1 разрешает ссылки R1C1 относительно координат ячейки, в которой живёт формула, GetTranslated заново строит дерево из классических байтов BIFF, а семейство GetStoreData записывает байты токенов обратно для хранения. MaxRow и MaxCol ограничивают ссылочную сетку, которую принимает компилятор, — движок XLSX поднимает их с умолчаний BIFF8 до сетки XLSX, а ссылки, не помещающиеся в BIFF8, не имеют ptg-формы, поэтому писатели BIFF8 сообщают о них как о некодируемых
ArrayFormulaMode выставляется, когда записывается rgce записи ARRAY (формула массива): ссылки класса значений и константы массивов тогда сериализуются как класс массива (tAreaA / tArrayA), как их и записывает сам Excel. С операндами класса значений Excel вычисляет формулу массива с неявным пересечением, а не как настоящую формулу массива — вот почему движки выставляют флаг для собственного rgce записи ARRAY
Ограниченный осмотр простого сохранённого листа (leaf)
TXLSCompiledFormula.ReadSimpleLeafInfo(ExpectedOwner, MaxBytes, MaxTextCharacters, AllowUnboundBiff) проверяет главное синтаксическое дерево и любой удерживаемый поток токенов на месте, без клонирования, декомпиляции, вычисления или материализации токенов и массивов; по умолчанию AllowUnboundBiff равен False
Поддерживаемые формы — один абсолютный лист REF3D или RANGE3D и один строковый литерал, причём при удерживаемом потоке токен ровно один и связный; выражения, относительные или смещённые ссылки, массивы, внешние данные массивов, неизвестные токены, несовпадающие главное и удерживаемое листья и чужие привязанные владельцы возвращают fslkUnsupported, не меняя кэшированные значения и состояние вычислений
| TXLSFormulaSimpleLeafKind | fslkUnsupported, fslkRange или fslkLiteral; проверьте Kind, прежде чем пользоваться остальными полями результата |
| TXLSFormulaLeafOwnerState | flosNoRetainedStream сообщает об отсутствии происхождения у потока токенов, flosUnboundStream сообщает об импортированном непривязанном BIFF, flosSameOwner сообщает о точном совпадении привязанного владельца, а flosForeignOwner отклоняет другого привязанного владельца |
| TXLSFormulaSimpleLeafInfo | Значимая запись без строк, содержащая Kind, OwnerState, RangeType, ExternId, FirstRow, FirstCol, LastRow, LastCol, TextCharacters, StoredTextCharacters, ReadBytes, SyntaxNodesи TokenCount |
| Range coordinates and identity | Координаты отсчитываются от нуля; ExternId — это логический идентификатор синтаксического дерева с отсчётом от единицы, а не индекс BIFF на проводе; вызывающий код должен разрешить его через закреплённую книгу и отклонять внешние книги, охваты листов, отсутствующие листы или координаты вне поддерживаемого диапазона захвата |
| Source costs | TextCharacters — длина литерального вывода в кодовых единицах UTF-16 или ноль для диапазона; StoredTextCharacters суммирует удерживаемый исходный текст, текст токена и проверенный текст синтаксиса; ReadBytes суммирует их двухбайтовую стоимость текста и длины удерживаемых исходных байтов, включая отдельно удерживаемые представления; эти счётчики описывают входы ограниченного осмотра, а не общее потребление кучи |
| Syntax and token counts | SyntaxNodes равен единице для простого скомпилированного листа или двум, когда проверяются и главное, и удерживаемое листья; TokenCount равен нулю без потока или единице при поддерживаемом связном удерживаемом потоке |
| TXLSFormulaTokenStream.ReadSimpleLeafInfo | Нижний слой принимает те же владельца и квоты, необязательный ComparedLeaf и необязательный ReferenceContext; он проверяет собственные приватные синтаксис, токены и исходные байты потока напрямую; ComparedLeaf добавляет проверки связности главного листа, а ReferenceContext отображает сериализованные внешние индексы текстовых формул без копирования |
| TXLSCompiledFormula.ReadSimpleLiteral | Принимает те же аргументы, повторяет проверки листа и возвращает принадлежащий вызывающему коду WideString только после того, как оставшиеся квоты байтов и символов покрывают и его вывод; неподдерживаемые листья или недостаточная оставшаяся ёмкость возбуждают EInvalidOperation |
ExpectedOwner должен быть точным калькулятором, присоединённым к потребляемому источнику, и оставаться живым и стабильным на протяжении всего осмотра и извлечения литерала; отсутствующий владелец возбуждает EArgumentException, отрицательные квоты — EArgumentOutOfRangeException, а слишком большие удерживаемые исходные данные — EInvalidOperation до сравнений содержимого или копирования вывода
Простой лист без удерживаемого потока не устанавливает своего исходного владельца; непривязанный импортированный поток также не несёт идентичности книги, поэтому явный AllowUnboundBiff=True уместен только когда вызывающий код уже закрепил исходный калькулятор и проверит локальную идентичность листа перед чтением ячеек; осмотр импортированных ссылок сейчас принимает ссылки BIFF8 и отклоняет отличающееся представление extern в BIFF5
Устаревшие синтаксические поля с именами FFirstRowRel, FFirstColRel, FLastRowRelи FLastColRel истинны для абсолютных координат; помощник также проверяет независимые флаги относительности токена и представление смещений, поэтому потребителям не нужно выводить абсолютные координаты из этих исторических имён
Syntax tree
CloneSyntaxTree returns a caller-owned parsed tree of TXLSSyntaxItem узлы для структурного осмотра: каждый узел сообщает свой ItemType, literal payload (Value, IntValue, DecValue), leading Spaces, tree links (Parent, Child, ChildCount), the reference leaf as a TXLSRangeItem through Range, and array-constant data (ArrayRows, ArrayCols, ArrayValueCount, and the TXLSArraySerVal entries in ArrayValues). Дерево — отсоединённая копия, поэтому его обход никогда не затрагивает скомпилированные формулы книги, а члены мутации (AddChild, PushChild, CopyObject, OffsetCopyReferences, AdjustForShift, and TXLSRangeItem.CopyObject / AdjustForShift) существуют для инструментов, которые переписывают клонированное дерево перед перекомпиляцией
Точки входа в книгу
Tokens := Worksheet.ParseFormulaTokens('SUM(A1:A4)', 1, 1);
try
if Tokens.ReplaceReference(OldRef, NewRef) then
Worksheet.SetFormulaTokens(1, 1, Tokens);
finally
Tokens.Free;
end;ParseFormulaTokens, GetFormulaTokens, FormulaTokensToTextи SetFormulaTokens сохраняют явное владение и проверяют контекст, версию BIFF, поддержку токенов, владение массивами и границы ссылок до изменения ячейки
Реестры пользовательских функций
TXLSUserFunctionResolver и TXLSUserFunctionRegistry обеспечивают поиск по имени через RegisterHandler, UnregisterHandler, Clear, Contains, TryGetHandlerи Count
Workbook.RegisterUserFunction('NETMARGIN', CalculateNetMargin);
Workbook.RegisterGlobalUserFunction('FISCALYEAR', CalculateFiscalYear);
try
Workbook.Calculate;
finally
Workbook.UnregisterUserFunction('NETMARGIN');
Workbook.UnregisterGlobalUserFunction('FISCALYEAR');
end;IXLSWorkbook, TXLSWorkbookи TXLSXWorkbook предоставляют RegisterUserFunction, UnregisterUserFunction, ClearUserFunctions, RegisteredUserFunctionCount, RegisterGlobalUserFunction, UnregisterGlobalUserFunction, ClearGlobalUserFunctionsи RegisteredGlobalUserFunctionCount
Эквивалентные точки входа уровня модуля — XLSRegisterGlobalUserFunction, XLSUnregisterGlobalUserFunction, XLSClearGlobalUserFunctions, XLSRegisteredGlobalUserFunctionCountи XLSGlobalUserFunctionRegistered
TXLSCalculator.OnUserFunctionResolve участвует до устаревшего резервного события, а обработчики реестра вызываются вне блокировки реестра, поэтому обработчик может безопасно отменить свою регистрацию
Опасные внешние и макро-имена функций блокируются до вычисления аргументов и поиска обработчика, если только AllowUnsafeFormulaCallbacks явно не включён для книги или отдельного контекстного вычисления; обычные имена пользовательских функций остаются доступными по умолчанию
Диагностика формул
TXLSXFormulaIssueKind, TXLSXFormulaLocationи TXLSXFormulaIssue возвращаются методом TXLSXWorkbook.AnalyzeFormulaIssues для отсутствующих функций, внешних ссылок и компонентов циклических зависимостей
Проверка макрос-листов
TXLSSheetKind различает лист, макрос-лист, лист диаграммы, модуль VBA и неизвестные записи листа через TXLSWorksheet.SheetKind; TXLSMacroRisk, TXLSMacroCommandInfoи TXLSMacroCommandArray описывают типизированные результаты TXLSWorksheet.ScanMacroCommands
Объединённый автоподбор и типы сортировки
TXLSMergedAutoFitStrategy и TXLSXMergedAutoFitStrategy выбирают рост первого, последнего или сбалансированный для объединённых диапазонов, а TXLSSortOrientation, TXLSSortFormulaModeи TXLSSortCompareEvent управляют вертикальной или горизонтальной устойчивой сортировкой и перемещением формул