HotXLS 문서

계산 및 변환 충실도

계산 배열은 선택, 정렬, 조회, 행렬, 모양 변경 함수를 넘나들며 조합되고, 자동 XLSX 스필 소유권, 명시적 CSE 대상, 제한된 평가 리소스를 갖춥니다

동적 배열과 명시적 CSE 배열

배열을 만드는 식을 TXLSXCell.Formula 하나에 대입하고 TXLSXWorkbook.Recalculate를 호출하세요. 결과는 그 셀에 앵커된 사각형 스필을 소유하며, SEQUENCE(3,2), A1:A3*10, 배열 상수, 배열을 반환하는 LET 결과 같은 수식이 여기에 해당합니다

Sheet.Cells.Item[1, 1].Formula := 'SEQUENCE(3,2)';
Sheet.Cells.Item[1, 4].Formula := 'SUM(A1#)';
Workbook.Recalculate;

재계산은 결과를 늘리거나 줄이고 앵커가 소유한 낡은 follower만 지우며, 범위가 바뀌면 종속성을 다시 만듭니다. 새 follower에 대한 참조와 A1# 스필 연산자는 현재 범위를 사용합니다

기존 값, 수식, 리치 텍스트, 다른 배열, 병합 범위, 테이블, 워크시트 경계는 스필을 막고 #SPILL!을 만듭니다. 비어 있는 셀의 스타일은 계속 쓸 수 있고, 장애물을 치우면 다음 재계산이 앵커를 다시 시도합니다

follower를 값이나 리치 텍스트로 편집하면 그 셀이 앵커에서 분리되어 다음 계산은 이 편집을 장애물로 보존합니다. 앵커를 지우거나 없애면 소유한 follower도 놓아주고, ConvertFormulasToValues는 계산된 값을 평범한 셀로 남깁니다

XLSX 저장은 현재 배열 범위와 메타데이터를 기록하고, 로딩은 재계산 전에 기존 캐시된 follower의 소유권을 복원합니다. 오류를 담은 배열 수식도 오류가 개별 요소에 속하는 한 범위를 유지합니다

SetArrayFormula는 두 통합 문서 엔진 모두에서 명시적인 고정 범위 CSE 진입점으로 남습니다. 원시 범위 산술은 그 범위 안에서 요소별로 평가되고, 평범한 스칼라 수식은 implicit intersection을 유지합니다

단항 @ 연산자는 참조를 수식 셀과 교차시키고 계산 배열의 첫 요소를 취합니다. SINGLE과 ANCHORARRAY는 implicit intersection과 스필 참조용 저장 별칭으로 받아들여집니다

MAP은 여러 입력 배열과 대응하는 LAMBDA 매개변수 목록을 받고, 요소 오류를 전파하며, 중첩 배열 결과는 #CALC!로 거부합니다. FILTER는 계산된 배열과 행·열 마스크를 받고, 오류 전파와 폴백이 없을 때의 빈 결과 #CALC!도 지원합니다

동적 스필 변경은 여러 계산 스레드를 설정해도 직렬로 실행됩니다. 범위 안정화는 32회로 제한되고, 순환 반복 계산 안의 동적 배열은 스칼라 결과로 취급되지 않고 거부됩니다

INDEX는 참조, 배열 상수, 계산 배열을 받습니다. 셀렉터가 둘 다 스칼라일 때 양의 행·열 셀렉터는 값 하나를, 0 셀렉터는 선택된 행이나 열을, 0 셀렉터 둘은 전체 배열을 반환합니다. 스칼라 셀렉터가 붙은 참조 소스는 ROW, ISREF 같은 소비자를 위해 참조 동작을 유지합니다

행·열 셀렉터는 배열일 수도 있습니다. 상수, 계산된 벡터, 범위 값, LET 바인딩이 모두 해당합니다. 서로 반대인 행·열 방향은 사각형 크로스 곱으로 브로드캐스트되고, 방향이 같으면 짝지은 위치를 선택합니다. 하나뿐인 차원은 브로드캐스트되고, 크기가 다른 차원에서 짝 없는 위치는 개별 #N/A를 반환합니다

한 셀렉터라도 배열이면 0이나 생략된 셀렉터는 행·열 전체를 펼치는 대신 해당 축의 첫 멤버를 고릅니다. 소수 셀렉터는 0 방향으로 잘리고, 음의 셀렉터는 잘리기 전에 개별 #VALUE!, 소스 경계를 넘는 셀렉터는 개별 #REF!를 반환합니다. 선택된 문자열, Boolean, 타입이 지정된 오류는 타입을 유지합니다

SORT와 UNIQUE는 범위, 상수, 계산 배열을 받으며 중첩된 FILTER, SEQUENCE, LET 결과도 포함입니다. 행·열 방향, 오름차순·내림차순 정렬, 첫 등장 순서, 정확히 한 번만 나오는 항목 추출은 소스 형태마다 같은 계약을 따릅니다

통합 문서 정의된 이름은 참조, 스칼라, 계산 배열 소스를 공급할 수 있습니다. ISREF(INDEX(...))는 실제 참조 결과와 이름 붙은 계산 값을 구별합니다. 스칼라 INDEX 셀렉터와 SORT 숫자 옵션은 소수 값을 자르고, 선택적 Boolean 인수는 TRUE나 FALSE가 아닌 텍스트를 거부합니다

Sheet.Cells.Item[1, 6].Formula := 'SORT(UNIQUE(FILTER(A1:B5,A1:A5>1)),1,-1)';
Sheet.Cells.Item[1, 9].Formula := 'INDEX(SORT(UNIQUE(A1:B5)),0,2)';
Sheet.Cells.Item[1, 12].Formula := 'INDEX(SEQUENCE(2,3,10,2),2,3)';
Workbook.Recalculate;
Sheet.Cells.Item[1, 1].Formula := 'INDEX(SEQUENCE(3,3),{1;3},{1,3})';
Workbook.Recalculate;

이 셀렉터 예는 2×2 결과로 {1,3;7,9}를 스필합니다. INDEX(SEQUENCE(3,3),{1;3},{1;3})은 대신 짝지은 열 {1;9}를 반환합니다. 배열 셀렉터는 소스가 참조여도 값을 만들고, 스칼라 참조 셀렉터는 참조 식별을 보존합니다

이 식들은 XLSX에서 스필·크기 조절되거나 명시적 CSE 대상 안에서 평가될 수 있습니다. 배열 소스 오류는 타입이 유지되고, 정확히 한 번만 나오는 항목이 없으면 #CALC!를 반환합니다. 셀렉터 출력은 평가 단계 예산을 소비하고, 소스·셀렉터·결과 행렬 페이로드의 합은 배열 메모리 예산으로 검사됩니다

INDEX는 계산 소스에 대해 명시적인 네 번째 area_num 인수로 1을 받으며, 행·열·영역 셀렉터는 지원되는 같은 시트 참조 유니온 위에서 함께 브로드캐스트될 수 있습니다. 실제 다중 영역 참조는 로컬 정의된 이름과 LET를 통해 식별을 유지하고, 스칼라 CHOOSE는 다른 시트의 선택을 포함해 선택된 참조를 유지합니다. 셀렉터 배열 결과는 중첩 참조 배열이 아니라 값입니다. 0, 누락, 강제 변환, 오류 규칙은 INDEX 영역 선택과 참조 식별을 참조하세요

독립 계산용으로 TXLSCalculator.OnGetSpillRange는 앵커의 현재 포함 경계를 해석하는 TXLSGetSpillRange 콜백을 받습니다. 통합 문서 기반 평가기는 이 콜백을 자동으로 설치합니다

TXLSGetSpillRange = function(SheetIndex, AnchorRow, AnchorCol: Integer;
  var LastRow, LastCol: Integer): Integer of object;

lxNormalizeStorageFormula는 작성된 수식 문법을 OOXML용으로 정규화하고, lxTryStorageFormulaOperators는 스필·implicit-intersection 연산자를 번역하며, lxApplyXlfnPrefix는 필요한 future-function 접두사를 붙입니다. 보호된 텍스트와 배열 행 구분자는 그대로 유지되고, 수식 대입은 호출자의 텍스트를 메모리에 유지합니다

저장은 메모리 속 작성된 식을 바꾸지 않습니다. 새로 작성된 XLSX 수식을 다시 열면 쉼표 인수와 선행 =가 없는 표준 저장 문법으로 돌아오며, 이는 네이티브 Excel 가져오기와 일치합니다. 바뀌지 않은 가져온 수식 XML은 기존 보존 경로를 유지합니다

조회, 행렬, 모양 변경 조합

TRANSPOSE는 참조, 상수, 계산 배열을 받으며 텍스트, Boolean, 개별 오류를 보존합니다. 빈 소스 셀은 숫자 0이 됩니다

MMULT, MDETERM, MINVERSE는 계산된 행렬과 MMULT(MUNIT(2),SEQUENCE(2,2)) 같은 중첩 식을 받습니다. 행렬 항목은 숫자여야 하고 텍스트, Boolean, 빈 항목은 강제 변환 없이 거부되며, 소스 오류는 오류 코드를 유지합니다

CHOOSECOLS와 CHOOSEROWS는 스칼라 또는 1차원 셀렉터 벡터를 받고, 인수 순서대로 셀렉터를 이어 붙이며, 중복을 보존하고, 음의 인덱스는 끝에서부터 셉니다. 소수 셀렉터는 0 방향으로 잘리고, 0과 범위 밖 셀렉터는 거부되며, 2차원 셀렉터 행렬은 지원되지 않습니다

XLOOKUP, XMATCH, MATCH는 계산된 조회 벡터와 배열 값을 갖는 조회 요청을 받습니다. 키는 한 행이나 한 열을 차지해야 하고, XLOOKUP 반환 배열은 그 조회 축과 정렬되어야 합니다

스칼라 XLOOKUP은 타입이 지정된 오류를 포함해 일치하는 행이나 열 전체를 반환할 수 있습니다. 배열 값 조회 요청은 자기 모양을 유지하며 일치하는 슬라이스나 폴백 배열의 첫 성분을 취합니다

정확 조회 스캔은 키 벡터의 오류 항목을 건너뜁니다. Boolean, 숫자, 텍스트 키는 서로 구별되고, 평범한 스칼라 참조 경로는 기존 스트리밍·재계산 캐시 동작을 유지합니다. 이진 탐색 모드는 여전히 올바르게 정렬된 키를 요구합니다

VSTACK, HSTACK, TAKE, DROP, TOROW, TOCOL, WRAPROWS, WRAPCOLS, EXPAND는 계산된 입력과 타입이 지정된 패딩을 받습니다. 행이나 열이 없는 결과는 #CALC!를 반환하고, 감싸기에는 1차원 입력이 필요합니다

행렬 작업, 조회 스캔, 셀렉터 순회, 복사, 패딩은 평가 단계 예산을 소비합니다. 동시에 유지되는 입력·작업·출력 행렬 페이로드는 할당 전에 설정된 배열 메모리 한도로 검사됩니다

Sheet.Cells.Item[1, 1].Formula := 'XLOOKUP({1;3},SEQUENCE(3),SEQUENCE(3,2))';
Sheet.Cells.Item[1, 4].Formula := 'CHOOSECOLS(SEQUENCE(2,3),{-1;1})';
Sheet.Cells.Item[1, 7].Formula := 'TRANSPOSE(UNIQUE({"A";"B";"A"}))';
Workbook.Recalculate;

타입이 지정된 최신 계산 오류

#SPILL!과 #CALC!는 계산, 표시, 캐시 검사, XLSX 다시 열기 전 과정에서 타입이 지정된 셀 오류로 유지됩니다. XLSX 출력은 리치 값 메타데이터를 실어 가며, 그 확장을 모르는 리더를 위한 표준 캐시 오류 폴백도 유지합니다

CSE와 동적 배열 follower를 포함한 수식 텍스트 결과는 리터럴 문자열 캐시를 사용해 재계산 전에도 Excel이 표시할 수 있습니다. 평범한 값 셀은 계속 공유 문자열을 씁니다

최신 리치 오류 출력은 재계산 전에 Excel이 캐시를 해석하는 데 필요한 통합 문서 버전과 Rich Data 계산 기능 선언을 포함합니다. 내보낸 calcId는 최소 191029이며 더 높은 요청 값은 보존되지만 통합 문서의 메모리 속 CalcId 프로퍼티는 바뀌지 않습니다

가져온 셀·값 메타데이터, 관련 없는 리치 값 구조, 불투명 버킷은 새 오류 버킷이 덧붙여져도 원래 식별을 유지합니다. 오류 셀을 교체하면 저장 시 낡은 타입 지정 오류 메타데이터가 지워집니다

TXLSXRichErrorCodes는 디코딩된 리치 오류 버킷용 정수 배열 타입입니다. 애플리케이션 코드는 셀의 Variant 값에서 타입이 지정된 오류를 읽습니다

BIFF8은 이런 최신 오류와 스필 연산자를 충실히 표현할 수 없습니다. Classic 직렬화기는 무관한 레거시 오류 코드를 할당하는 대신 지원되지 않는 최신 표현을 거부합니다

변환 프리플라이트

TXLSXWorkbook.GetConversionReport는 재계산이나 통합 문서 변경 없이 호출자 소유의 TXLSConversionReport를 반환합니다. 타입은 lxDiagnostics에 선언되어 있습니다

Report := Workbook.GetConversionReport(xlsConversionOpenDocument);
try
  for I := 0 to Report.Count - 1 do
    InspectIssue(Report.Items[I]);
finally
  Report.Free;
end;
TargetxlsConversionOpenXmlWorkbook, xlsConversionOpenXmlTemplate, xlsConversionMacroEnabledTemplate, xlsConversionOpenDocument, xlsConversionExcel97Workbook, 또는 xlsConversionExcelBinaryWorkbook
FidelityTXLSConversionFidelity: xlsConversionPreserved, xlsConversionDegraded, xlsConversionDropped, 또는 xlsConversionUnsupported
IssueTXLSConversionIssue는 Feature, Fidelity, SheetIndex, SheetName, Location, Message를 노출합니다. HasLoss는 degraded, dropped, unsupported 항목을 포함합니다

보고서는 VBA, 보호, 통합 문서 뷰, 연결, 쿼리 테이블, 주석, 외부 링크, XML 맵, 테이블 구조, 필터 조건, 도형, 타입 지정 오류 캐시, 지원되지 않는 유효성 검사나 수식 문법, 배열 소유권, 불투명 확장 파트 같은 알려진 형식 손실을 조사합니다. 구현된 변환 경로를 서술할 뿐 모든 외부 애플리케이션의 모든 기능을 보증하지는 않습니다

ODS는 평범한 표 셀, 캐시된 수식 결과, 지원되는 주석 텍스트와 작성자, 암호 없는 워크시트 보호, 표현 가능한 필터를 유지하는 대신 Excel 테이블 개체, 더 풍부한 차트 기하, 지원되지 않는 규칙 시맨틱을 잃습니다. 대상이 담을 수 없는 불투명 OOXML 보존 페이로드는 dropped로 보고됩니다

XLSX 퍼사드는 BIFF8 출력을 unsupported로 보고합니다. 지원되는 BIFF 워크플로에는 Classic 통합 문서 API를 사용하세요. 버전 2.384.93은 검증·비검증 저장 모두에서 표현되지 않는 수식, 기능 개체, 메타데이터, 계산 설정을 거부하는 제한된 XLSB 값·스타일 백엔드를 추가합니다

검증된 저장

Status := Workbook.SaveAsChecked(Stream,
  xlsxOpenDocumentSpreadsheet, False);

파일·스트림 오버로드는 쓰기 전에 알려진 손실 프리플라이트를 실행합니다. AllowLossy=False는 degraded·dropped 기능을 변환 진단과 함께 거부하고, AllowLossy=True는 그 손실을 명시적으로 받아들이면서 unsupported 변환은 여전히 거부합니다

거부된 프리플라이트는 대상 바이트와 스트림 위치를 그대로 둡니다. 성공한 요청은 기존 저장 트랜잭션을 쓰고 SaveAs와 같은 저장 상태 규약을 반환합니다

평범한 SaveAs도 기존 동작 그대로 계속 쓸 수 있습니다. 명시적인 손실 판단이 필요한 애플리케이션은 보고서를 확인하고 검증된 저장을 사용하세요

템플릿 형식

xlsxOpenXMLTemplate은 매크로 없는 XLTX를 고르고, xlsxOpenXMLMacroEnabledTemplate은 XLTM을 골라 기존 VBA 프로젝트를 보존합니다. 형식은 명시적이며 파일 확장자나 가져온 템플릿에서 추론되지 않습니다

매크로 없는 XLTX는 lossy 검증 저장을 켜 둔 경우라도 VBA를 담은 통합 문서를 거부합니다. XLTM 패키지는 VBA 프로젝트 없이 내보낼 수 있고, HotXLS는 VBA 코드를 만들지 않습니다

ODS 유효성 검사 수식

커스텀 Boolean 유효성 검사는 of:is-true-formula(...)를 사용합니다. 지원되는 스칼라 경계, 목록 소스, 한정된 A1 참조, 문자열, 인수 구분자는 OpenFormula로 번역되고 가져오기 때 유효성 검사 기준 셀 주소를 기준으로 다시 잡힙니다

지원되지 않는 구조화·외부·3차원 유효성 검사 식은 셀 참조와 함께 생략되어 유효성 검사 정의가 매달려 있는 상태를 피합니다. 변환 프리플라이트는 생략된 규칙을 보고합니다

ODS 주석, 보호, 필터

평범한 셀 주석은 텍스트와 작성자를 포함해 OpenDocument 주석으로 내보내지며, 빈 메모, 탭, 공백, 줄바꿈도 포함됩니다. 없는 셀의 메모와 먼 좌표는 워크시트 셀을 만들지 않고 희소한 반복 행·열 런을 사용합니다

병합 범위 앵커 셀의 주석은 주소를 유지합니다. 덮인 셀이나 워크시트 격자 밖의 메모는 dropped로 보고됩니다. 리치 주석 텍스트는 표시 텍스트로 평탄화되며, 변환 보고서는 런 서식, 커스텀 상자 크기, 항상 보이기 표현의 손실을 식별합니다

OpenDocument 보호 플래그와 지원되는 잠금·잠금 해제 셀 스타일은 유지됩니다. 무손실 워크시트 부분집합은 암호나 편집 가능 범위 예외를 쓰지 않고 잠긴 셀과 잠금 해제 셀의 선택만 허용합니다

Sheet.Protect;
Sheet.SheetProtectionOptions :=
  [xlsxSpoSelectLockedCells, xlsxSpoSelectUnlockedCells];
Sheet.Range['B2:B100'].Locked := False;

Excel 암호 해시, 최신 암호 설정, 편집 가능 범위, 그 부분집합 밖의 동작 권한은 보호 플래그가 남아 있는 가운데 degraded로 보고됩니다. Excel의 넓은 기본 권한 집합도 명시적인 손실 판단이 필요합니다

OpenDocument 가져오기는 보호 플래그와 셀 잠금 스타일을 유지합니다. 네이티브 암호 해시는 Excel 해시로 변환되지 않고, 표현되지 않는 가져온 권한 메타데이터는 이후 변환 보고서에서 이름 붙은 손실로 남습니다

AutoFilter 내보내기는 여섯 스칼라 비교 연산자, 열당 AND 또는 OR로 연결된 최대 두 개의 스칼라 조건, 열 사이의 AND를 지원합니다. 지원되는 평범한 값 선택 목록과 빈 선택은 두 값 제한이 없으며 네이티브 필터 메타데이터로 남습니다

숫자 스칼라 조건은 불변 유한 값을 씁니다. 텍스트 선택은 선택 목록 안의 와일드카드 문자를 포함해 리터럴 문자를 보존하고, 커스텀 필터의 와일드카드 식, 모호한 Boolean 조건, 날짜 그룹, 동적 날짜, 색·아이콘 필터에는 지원되는 동등한 변환이 없습니다

지원되지 않는 필터 식은 선택된 조건을 약화시키는 대신 식 전체로 생략됩니다. 필터 범위는 남고, 변환 보고서는 생략된 조건을 식별합니다

ODS 스트림 저장은 대상의 원래 위치에 쓰기 전에 완성된 패키지를 등록된 임시 파일에 스테이징합니다. 기존 접두 바이트와 절대 ZIP 오프셋은 원래 끝 너머의 위치까지 보존됩니다. 커밋 전 취소나 진행 콜백 예외는 대상 바이트, 크기, 위치를 보존하고 임시 파일을 해제합니다. 최종 쓰기 알림은 취소할 수 없습니다

OpenDocument 가져오기는 같은 스칼라 결합과 같은 열 텍스트 선택(OR)·값 집합을 지원합니다. 교차 열 OR, 정규식, 대소문자 구분 비교, 지원되지 않는 네이티브 필터 연산자는 명시적인 가져오기 손실로 남습니다

TXLSXOdsImportLoss와 TXLSXOdsImportLosses는 비공개 워크시트 출처(provenance) 범주를 서술합니다. 변환 보고서는 ImportedOdsProtectionPassword, ImportedOdsProtectionOptions, ImportedOdsFilterCriteria, ImportedOdsCommentFormatting를 사용하며, 이들은 워크시트 복사에서 살아남고 OpenDocument와 Open XML 변환 대상 모두에서 나타납니다

필터 변환은 필터를 적용하거나 셀을 재계산하지 않으면서 메타데이터와 기존 행 표시 여부를 유지합니다. 네이티브 애플리케이션은 자체 필터링과 편집 동작의 책임을 유지합니다

관련 워크플로