├── .gitignore ├── Excel4Delphi.Common.pas ├── Excel4Delphi.ExportHTML.pas ├── Excel4Delphi.Formula.pas ├── Excel4Delphi.NumberFormat.pas ├── Excel4Delphi.Stream.pas ├── Excel4Delphi.XlsxStream.pas ├── Excel4Delphi.Xml.pas ├── Excel4Delphi.groupproj ├── Excel4Delphi.pas ├── Excel4DelphiLib.dpk ├── Excel4DelphiLib.dproj ├── LICENSE.TXT ├── README.MD └── Test ├── Examples └── Test1.xlsx ├── Excel4DelphiLibTest.dpr ├── Excel4DelphiLibTest.dproj ├── Excel4DelphiTest.Converters.pas ├── Excel4DelphiTest.Formula.pas └── Excel4DelphiTest.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE! Don't add files that are generated in specific 3 | # subdirectories here. Add them in the ".gitignore" file 4 | # in that subdirectory instead. 5 | # 6 | # NOTE! Please use 'git-ls-files -i --exclude-standard' 7 | # command after changing this file, to see if there are 8 | # any tracked files which get ignored after the change. 9 | # 10 | # Normal rules 11 | # 12 | 13 | *.vrc 14 | *.vlb 15 | *.dcu 16 | *.res 17 | *.cfg 18 | *.dcp 19 | *.dsk 20 | *.identcache 21 | *.~dsk 22 | *.hlp 23 | *.gid 24 | *.cnt 25 | *.fts 26 | *.diff 27 | *.patch 28 | *.stat 29 | *.tmp 30 | 31 | *.pdb 32 | *.~*~ 33 | ~$* 34 | *.bak 35 | *.$$$ 36 | 37 | *.inf 38 | *.dat 39 | *.ini 40 | *.exe 41 | *.dll 42 | *.log 43 | *.cbk 44 | *.orig 45 | *.rar 46 | *.zip 47 | *.xml 48 | *.dproj.local 49 | *.groupproj.local 50 | *.tvsconfig 51 | *.vshost.exe.manifest 52 | 53 | Win32/Debug/* 54 | Win64/Debug/* 55 | Win32/Release/* 56 | Win64/Release/* 57 | 58 | Test/Win32/Debug/* 59 | Test/Win64/Debug/* 60 | Test/Win32/Release/* 61 | Test/Win64/Release/* 62 | 63 | **/__history/* 64 | **/__recovery/* 65 | **/__astcache/* 66 | -------------------------------------------------------------------------------- /Excel4Delphi.Common.pas: -------------------------------------------------------------------------------- 1 | unit Excel4Delphi.Common; 2 | 3 | interface 4 | 5 | uses 6 | SysUtils, 7 | Types, 8 | Classes, 9 | Excel4Delphi, 10 | Excel4Delphi.Xml; 11 | 12 | const 13 | ZE_MMinInch: real = 25.4; 14 | 15 | type 16 | TTempFileStream = class(THandleStream) 17 | private 18 | FFileName: string; 19 | public 20 | constructor Create(); 21 | destructor Destroy; override; 22 | property FileName: string read FFileName; 23 | end; 24 | 25 | //Попытка преобразовать строку в число 26 | function ZEIsTryStrToFloat(const st: string; out retValue: double): boolean; 27 | function ZETryStrToFloat(const st: string; valueIfError: double = 0): double; overload; 28 | function ZETryStrToFloat(const st: string; out isOk: boolean; valueIfError: double = 0): double; overload; 29 | /// 30 | /// Try convert string (any formats) to datetime 31 | /// 32 | function ZETryParseDateTime(const AStrDateTime: string; out retDateTime: TDateTime): boolean; 33 | /// 34 | /// Try convert string (YYYY-MM-DDTHH:MM:SS[.mmm]) to datetime 35 | /// 36 | function TryZEStrToDateTime(const AStrDateTime: string; out retDateTime: TDateTime): boolean; 37 | 38 | //Попытка преобразовать строку в boolean 39 | function ZETryStrToBoolean(const st: string; valueIfError: boolean = false): boolean; 40 | 41 | //заменяет все запятые на точки 42 | function ZEFloatSeparator(st: string): string; 43 | 44 | //Проверяет заголовки страниц, при необходимости корректирует 45 | function ZECheckTablesTitle(var XMLSS: TZWorkBook; const SheetsNumbers:array of integer; 46 | const SheetsNames: array of string; out _pages: TIntegerDynArray; 47 | out _names: TStringDynArray; out retCount: integer): boolean; 48 | 49 | //Очищает массивы 50 | procedure ZESClearArrays(var _pages: TIntegerDynArray; var _names: TStringDynArray); 51 | 52 | //Переводит строку в boolean 53 | function ZEStrToBoolean(const val: string): boolean; 54 | 55 | /// 56 | /// Decodes the input HTML data and returns the decoded HTML data. 57 | /// 58 | function ZEReplaceEntity(const text: string): string; 59 | 60 | // despite formal angle datatype declaration in default "range check off" mode 61 | // it can be anywhere -32K to +32K 62 | // This fn brings it back into -90 .. +90 range 63 | function ZENormalizeAngle90(const value: TZCellTextRotate): integer; 64 | 65 | /// 66 | /// Despite formal angle datatype declaration in default "range check off" mode it can be anywhere -32K to +32K 67 | /// This fn brings it back into 0 .. +179 range 68 | /// 69 | function ZENormalizeAngle180(const value: TZCellTextRotate): integer; 70 | 71 | implementation 72 | 73 | uses 74 | DateUtils, IOUtils, Winapi.Windows, Variants, VarUtils, NetEncoding; 75 | 76 | function FileCreateTemp(var tempName: string): THandle; 77 | begin 78 | Result := INVALID_HANDLE_VALUE; 79 | TempName := TPath.GetTempFileName(); 80 | if TempName <> '' then begin 81 | Result := CreateFile(PChar(TempName), GENERIC_READ or GENERIC_WRITE, 0, nil, 82 | OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0); 83 | if Result = INVALID_HANDLE_VALUE then 84 | TFile.Delete(TempName); 85 | end; 86 | end; 87 | 88 | constructor TTempFileStream.Create(); 89 | var FileHandle: THandle; 90 | begin 91 | FileHandle := FileCreateTemp(FFileName); 92 | if FileHandle = INVALID_HANDLE_VALUE then 93 | raise Exception.Create('The file cannot be created.'); 94 | inherited Create(FileHandle); 95 | end; 96 | 97 | destructor TTempFileStream.Destroy; 98 | begin 99 | if THandle(Handle) <> INVALID_HANDLE_VALUE then 100 | FileClose(Handle); 101 | inherited Destroy; 102 | end; 103 | 104 | // despite formal angle datatype declaration in default "range check off" mode 105 | // it can be anywhere -32K to +32K 106 | // This fn brings it back into -90 .. +90 range for Excel XML 107 | function ZENormalizeAngle90(const value: TZCellTextRotate): integer; 108 | var Neg: boolean; A: integer; 109 | begin 110 | if (value >= -90) and (value <= +90) 111 | then Result := value 112 | else begin (* Special values: 270; 450; -450; 180; -180; 135 *) 113 | Neg := Value < 0; (* F, F, T, F, T, F *) 114 | A := Abs(value) mod 360; // 0..359 (* 270, 90, 90, 180, 180, 135 *) 115 | if A > 180 then A := A - 360; // -179..+180 (* -90, 90, 90, 180, 180, 135 *) 116 | if A < 0 then begin 117 | Neg := not Neg; (* T, -"- F, T, F, T, F *) 118 | A := - A; // 0..180 (* 90, -"- 90, 90, 180, 180, 135 *) 119 | end; 120 | if A > 90 then A := A - 180; // 91..180 -> -89..0 (* 90, 90, 90, 0, 0, -45 *) 121 | Result := A; 122 | If Neg then Result := - Result; (* -90, +90, -90, 0, 0, -45 *) 123 | end; 124 | end; 125 | 126 | // despite formal angle datatype declaration in default "range check off" mode 127 | // it can be anywhere -32K to +32K 128 | // This fn brings it back into 0 .. +180 range 129 | function ZENormalizeAngle180(const value: TZCellTextRotate): integer; 130 | begin 131 | Result := ZENormalizeAngle90(value); 132 | If Result < 0 then Result := 90 - Result; 133 | end; 134 | 135 | 136 | function ZEReplaceEntity(const text: string): string; 137 | begin 138 | result := TNetEncoding.HTML.Decode(text); 139 | end; 140 | 141 | //Переводит строку в boolean 142 | //INPUT 143 | // const val: string - переводимая строка 144 | function ZEStrToBoolean(const val: string): boolean; 145 | begin 146 | if (val = '1') or (UpperCase(val) = 'TRUE') then 147 | result := true 148 | else 149 | result := false; 150 | end; 151 | 152 | //Попытка преобразовать строку в boolean 153 | // const st: string - строка для распознавания 154 | // valueIfError: boolean - значение, которое подставляется при ошибке преобразования 155 | function ZETryStrToBoolean(const st: string; valueIfError: boolean = false): boolean; 156 | begin 157 | result := valueIfError; 158 | if (st > '') then begin 159 | if CharInSet(st[1], ['T', 't', '1', '-']) then 160 | result := true 161 | else 162 | if CharInSet(st[1], ['F', 'f', '0']) then 163 | result := false 164 | else 165 | result := valueIfError; 166 | end; 167 | end; //ZETryStrToBoolean 168 | 169 | function ZEIsTryStrToFloat(const st: string; out retValue: double): boolean; 170 | begin 171 | retValue := ZETryStrToFloat(st, Result); 172 | end; 173 | 174 | //Попытка преобразовать строку в число 175 | //INPUT 176 | // const st: string - строка 177 | // out isOk: boolean - если true - ошибки небыло 178 | // valueIfError: double - значение, которое подставляется при ошибке преобразования 179 | function ZETryStrToFloat(const st: string; out isOk: boolean; valueIfError: double = 0): double; 180 | var 181 | s: string; 182 | i: integer; 183 | n: integer; 184 | c: integer; 185 | done: boolean; 186 | hasSep: boolean; 187 | begin 188 | Result := valueIfError; 189 | SetLength(s, Length(st)); 190 | n := 0; 191 | done := false; 192 | hasSep := false; 193 | isOk := false; 194 | for i := 1 to Length(st) do 195 | begin 196 | c := Ord(st[i]); 197 | if c = 32 then 198 | begin 199 | if n > 0 then 200 | done := true; 201 | continue; 202 | end 203 | else if (c >= 48) and (c <= 57) then 204 | begin 205 | if done then 206 | exit; // Если уже был пробел и опять пошли цифры, то это ошибка, поэтому выходим. 207 | Inc(n); 208 | s[n] := Char(c); 209 | end 210 | else if c in [44, 46] then 211 | begin 212 | if done or hasSep then 213 | exit; // Если уже был пробел или разделитель и опять попался разделитель, то это ошибка, поэтому выходим. 214 | Inc(n); 215 | s[n] := FormatSettings.DecimalSeparator; 216 | hasSep := true; 217 | end; 218 | end; 219 | if n > 0 then 220 | begin 221 | SetLength(s, n); 222 | isOk := TryStrToFloat(s, Result); 223 | if (not isOk) then 224 | Result := valueIfError; 225 | end; 226 | end; //ZETryStrToFloat 227 | 228 | //Попытка преобразовать строку в число 229 | //INPUT 230 | // const st: string - строка 231 | // valueIfError: double - значение, которое подставляется при ошибке преобразования 232 | function ZETryStrToFloat(const st: string; valueIfError: double = 0): double; 233 | var isOk: boolean; 234 | begin 235 | Result := ZETryStrToFloat(st, isOk, valueIfError); 236 | end; //ZETryStrToFloat 237 | 238 | //заменяет все запятые на точки 239 | function ZEFloatSeparator(st: string): string; 240 | var k: integer; 241 | begin 242 | result := ''; 243 | for k := 1 to length(st) do 244 | if (st[k] = ',') then 245 | result := result + '.' 246 | else 247 | result := result + st[k]; 248 | end; 249 | 250 | function ZETryParseDateTime(const AStrDateTime: string; out retDateTime: TDateTime): boolean; 251 | var err: Integer; 252 | doubleVal: Double; 253 | LResult: HResult; 254 | begin 255 | result := false; 256 | 257 | if TryZEStrToDateTime(AStrDateTime, retDateTime) then 258 | exit(true); 259 | 260 | retDateTime := StrToDateDef(AStrDateTime, 0); 261 | if retDateTime > 0 then 262 | exit(true); 263 | 264 | retDateTime := StrToDateTimeDef(AStrDateTime, 0); 265 | if retDateTime > 0 then 266 | exit(true); 267 | 268 | Val(AStrDateTime, retDateTime, err); 269 | if err = 0 then 270 | exit(true); 271 | 272 | LResult := VarDateFromStr(PWideChar(AStrDateTime), VAR_LOCALE_USER_DEFAULT, 0, retDateTime); 273 | if LResult = VAR_OK then 274 | exit(true); 275 | 276 | if LResult = VAR_TYPEMISMATCH then begin 277 | if not TryStrToDate(PWideChar(AStrDateTime), retDateTime) then begin 278 | if TryStrToFloat(AStrDateTime, doubleVal) then begin 279 | retDateTime := doubleVal; 280 | exit(true); 281 | end; 282 | end; 283 | end; 284 | 285 | Val(AStrDateTime, doubleVal, err); 286 | if err = 0 then begin 287 | retDateTime := doubleVal; 288 | exit(true); 289 | end; 290 | 291 | retDateTime := 0; 292 | end; 293 | 294 | function TryZEStrToDateTime(const AStrDateTime: string; out retDateTime: TDateTime): boolean; 295 | var a: array [0..10] of word; 296 | i, l: integer; 297 | s, ss: string; 298 | count: integer; 299 | ch: char; 300 | datedelimeters: integer; 301 | istimesign: boolean; 302 | timedelimeters: integer; 303 | istimezone: boolean; 304 | lastdateindex: integer; 305 | tmp: integer; 306 | msindex: integer; 307 | tzindex: integer; 308 | timezonemul: integer; 309 | _ms: word; 310 | 311 | function TryAddToArray(const ST: string): boolean; 312 | begin 313 | if (count > 10) then begin 314 | Result := false; 315 | exit; 316 | end; 317 | Result := TryStrToInt(ST, tmp); 318 | if (Result) then begin 319 | a[Count] := word(tmp); 320 | inc(Count); 321 | end 322 | end; 323 | 324 | procedure _CheckDigits(); 325 | var _l: integer; 326 | begin 327 | _l := length(s); 328 | if (_l > 0) then begin 329 | if (_l > 4) then begin//it is not good 330 | if (istimesign) then begin 331 | // HHMMSS? 332 | if (_l = 6) then begin 333 | ss := copy(s, 1, 2); 334 | if (TryAddToArray(ss)) then begin 335 | ss := copy(s, 3, 2); 336 | if (TryAddToArray(ss)) then begin 337 | ss := copy(s, 5, 2); 338 | if (not TryAddToArray(ss)) then 339 | Result := false; 340 | end else 341 | Result := false; 342 | end else 343 | Result := false 344 | end else 345 | Result := false; 346 | end else begin 347 | // YYYYMMDD? 348 | if (_l = 8) then begin 349 | ss := copy(s, 1, 4); 350 | if (not TryAddToArray(ss)) then 351 | Result := false 352 | else begin 353 | ss := copy(s, 5, 2); 354 | if (not TryAddToArray(ss)) then 355 | Result := false 356 | else begin 357 | ss := copy(s, 7, 2); 358 | if (not TryAddToArray(ss)) then 359 | Result := false; 360 | end; 361 | end; 362 | end else 363 | Result := false; 364 | end; 365 | end else 366 | if (not TryAddToArray(s)) then 367 | Result := false; 368 | end; //if 369 | if (Count > 10) then 370 | Result := false; 371 | s := ''; 372 | end; 373 | 374 | procedure _processDigit(); 375 | begin 376 | s := s + ch; 377 | end; 378 | 379 | procedure _processTimeSign(); 380 | begin 381 | istimesign := true; 382 | if (count > 0) then 383 | lastdateindex := count; 384 | 385 | _CheckDigits(); 386 | end; 387 | 388 | procedure _processTimeDelimiter(); 389 | begin 390 | _CheckDigits(); 391 | inc(timedelimeters) 392 | end; 393 | 394 | procedure _processDateDelimiter(); 395 | begin 396 | _CheckDigits(); 397 | if (istimesign) then begin 398 | tzindex := count; 399 | istimezone := true; 400 | timezonemul := -1; 401 | end else 402 | inc(datedelimeters); 403 | end; 404 | 405 | procedure _processMSDelimiter(); 406 | begin 407 | _CheckDigits(); 408 | msindex := count; 409 | end; 410 | 411 | procedure _processTimeZoneSign(); 412 | begin 413 | _CheckDigits(); 414 | istimezone := true; 415 | end; 416 | 417 | procedure _processTimeZonePlus(); 418 | begin 419 | _CheckDigits(); 420 | istimezone := true; 421 | timezonemul := -1; 422 | end; 423 | 424 | function _TryGetDateTime(): boolean; 425 | var _time, _date: TDateTime; 426 | begin 427 | //Result := true; 428 | if (msindex >= 0) then 429 | _ms := a[msindex]; 430 | if (lastdateindex >= 0) then begin 431 | Result := TryEncodeDate(a[0], a[1], a[2], _date); 432 | if (Result) then begin 433 | Result := TryEncodeTime(a[lastdateindex + 1], a[lastdateindex + 2], a[lastdateindex + 3], _ms, _time); 434 | if (Result) then 435 | retDateTime := _date + _time; 436 | end; 437 | end else 438 | Result := TryEncodeTime(a[lastdateindex + 1], a[lastdateindex + 2], a[lastdateindex + 3], _ms, retDateTime); 439 | end; 440 | 441 | function _TryGetDate(): boolean; 442 | begin 443 | if (datedelimeters = 0) and (timedelimeters >= 2) then begin 444 | if (msindex >= 0) then 445 | _ms := a[msindex]; 446 | result := TryEncodeTime(a[0], a[1], a[2], _ms, retDateTime); 447 | end else if (count >= 3) then 448 | Result := TryEncodeDate(a[0], a[1], a[2], retDateTime) 449 | else 450 | Result := false; 451 | end; 452 | 453 | begin 454 | Result := true; 455 | datedelimeters := 0; 456 | istimesign := false; 457 | timedelimeters := 0; 458 | istimezone := false; 459 | lastdateindex := -1; 460 | msindex := -1; 461 | tzindex := -1; 462 | timezonemul := 0; 463 | _ms := 0; 464 | FillChar(a, sizeof(a), 0); 465 | 466 | l := length(AStrDateTime); 467 | s := ''; 468 | count := 0; 469 | for i := 1 to l do begin 470 | ch := AStrDateTime[i]; 471 | case (ch) of 472 | '0'..'9': _processDigit(); 473 | 't', 'T': _processTimeSign(); 474 | '-': _processDateDelimiter(); 475 | ':': _processTimeDelimiter(); 476 | '.', ',': _processMSDelimiter(); 477 | 'z', 'Z': _processTimeZoneSign(); 478 | '+': _processTimeZonePlus(); 479 | end; 480 | if (not Result) then 481 | break 482 | end; 483 | 484 | if (Result and (s <> '')) then 485 | _CheckDigits(); 486 | 487 | if (Result) then begin 488 | if (istimesign) then 489 | Result := _TryGetDateTime() 490 | else 491 | Result := _TryGetDate(); 492 | end; 493 | end; //TryZEStrToDateTime 494 | 495 | //Очищает массивы 496 | procedure ZESClearArrays(var _pages: TIntegerDynArray; var _names: TStringDynArray); 497 | begin 498 | SetLength(_pages, 0); 499 | SetLength(_names, 0); 500 | _names := nil; 501 | _pages := nil; 502 | end; 503 | 504 | resourcestring DefaultSheetName = 'Sheet'; 505 | 506 | //делает уникальную строку, добавляя к строке '(num)' 507 | //топорно, но работает 508 | //INPUT 509 | // var st: string - строка 510 | // n: integer - номер 511 | procedure ZECorrectStrForSave(var st: string; n: integer); 512 | var l, i, m, num: integer; s: string; 513 | begin 514 | if Trim(st) = '' then 515 | st := DefaultSheetName; // behave uniformly with ZECheckTablesTitle 516 | 517 | l := length(st); 518 | if st[l] <> ')' then 519 | st := st + '(' + inttostr(n) + ')' 520 | else 521 | begin 522 | m := l; 523 | for i := l downto 1 do 524 | if st[i] = '(' then begin 525 | m := i; 526 | break; 527 | end; 528 | if m <> l then begin 529 | s := copy(st, m+1, l-m - 1); 530 | try 531 | num := StrToInt(s) + 1; 532 | except 533 | num := n; 534 | end; 535 | delete(st, m, l-m + 1); 536 | st := st + '(' + inttostr(num) + ')'; 537 | end else 538 | st := st + '(' + inttostr(n) + ')'; 539 | end; 540 | end; //ZECorrectStrForSave 541 | 542 | //делаем уникальные значения массивов 543 | //INPUT 544 | // var mas: array of string - массив со значениями 545 | procedure ZECorrectTitles(var mas: array of string); 546 | var i, num, k, _kol: integer; s: string; 547 | begin 548 | num := 0; 549 | _kol := High(mas); 550 | while (num < _kol) do begin 551 | s := UpperCase(mas[num]); 552 | k := 0; 553 | for i := num + 1 to _kol do begin 554 | if (s = UpperCase(mas[i])) then begin 555 | inc(k); 556 | ZECorrectStrForSave(mas[i], k); 557 | end; 558 | end; 559 | inc(num); 560 | if k > 0 then num := 0; 561 | end; 562 | end; //CorrectTitles 563 | 564 | //Проверяет заголовки страниц, при необходимости корректирует 565 | //INPUT 566 | // var XMLSS: TZWorkBook 567 | // const SheetsNumbers:array of integer 568 | // const SheetsNames: array of string 569 | // var _pages: TIntegerDynArray 570 | // var _names: TStringDynArray 571 | // var retCount: integer 572 | //RETURN 573 | // boolean - true - всё нормально, можно продолжать дальше 574 | // false - что-то не то подсунули, дальше продолжать нельзя 575 | function ZECheckTablesTitle(var XMLSS: TZWorkBook; const SheetsNumbers:array of integer; 576 | const SheetsNames: array of string; out _pages: TIntegerDynArray; 577 | out _names: TStringDynArray; out retCount: integer): boolean; 578 | var t1, t2, i: integer; 579 | // '!' is allowed; ':' is not; whatever else ? 580 | procedure SanitizeTitle(var s: string); var i: integer; 581 | begin 582 | s := Trim(s); 583 | for i := 1 to length(s) do 584 | if s[i] = ':' then s[i] := ';'; 585 | end; 586 | function CoalesceTitle(const i: integer; const checkArray: boolean): string; 587 | begin 588 | if checkArray then begin 589 | Result := SheetsNames[i]; 590 | SanitizeTitle(Result); 591 | end else 592 | Result := ''; 593 | 594 | if Result = '' then begin 595 | Result := XMLSS.Sheets[_pages[i]].Title; 596 | SanitizeTitle(Result); 597 | end; 598 | 599 | if Result = '' then 600 | Result := DefaultSheetName + ' ' + IntToStr(_pages[i] + 1); 601 | end; 602 | 603 | begin 604 | result := false; 605 | t1 := Low(SheetsNumbers); 606 | t2 := High(SheetsNumbers); 607 | retCount := 0; 608 | //если пришёл пустой массив SheetsNumbers - берём все страницы из Sheets 609 | if t1 = t2 + 1 then 610 | begin 611 | retCount := XMLSS.Sheets.Count; 612 | setlength(_pages, retCount); 613 | for i := 0 to retCount - 1 do 614 | _pages[i] := i; 615 | end else 616 | begin 617 | //иначе берём страницы из массива SheetsNumbers 618 | for i := t1 to t2 do 619 | begin 620 | if (SheetsNumbers[i] >= 0) and (SheetsNumbers[i] < XMLSS.Sheets.Count) then 621 | begin 622 | inc(retCount); 623 | setlength(_pages, retCount); 624 | _pages[retCount-1] := SheetsNumbers[i]; 625 | end; 626 | end; 627 | end; 628 | 629 | if (retCount <= 0) then 630 | exit; 631 | 632 | //названия страниц 633 | // t1 := Low(SheetsNames); // we anyway assume later that Low(_names) == t1 - then let us just skip this. 634 | t2 := High(SheetsNames); 635 | setlength(_names, retCount); 636 | // if t1 = t2 + 1 then 637 | // begin 638 | // for i := 0 to retCount - 1 do 639 | // begin 640 | // _names[i] := XMLSS.Sheets[_pages[i]].Title; 641 | // if trim(_names[i]) = '' then _names[i] := 'list'; 642 | // end; 643 | // end else 644 | // begin 645 | // if (t2 > retCount) then 646 | // t2 := retCount - 1; 647 | // for i := t1 to t2 do 648 | // _names[i] := SheetsNames[i]; 649 | // if (t2 < retCount) then 650 | // for i := t2 + 1 to retCount - 1 do 651 | // begin 652 | // _names[i] := XMLSS.Sheets[_pages[i]].Title; 653 | // if trim(_names[i]) = '' then _names[i] := 'list'; 654 | // end; 655 | // end; 656 | for i := Low(_names) to High(_names) do begin 657 | _names[i] := CoalesceTitle(i, i <= t2); 658 | end; 659 | 660 | 661 | ZECorrectTitles(_names); 662 | result := true; 663 | end; //ZECheckTablesTitle 664 | 665 | end. 666 | -------------------------------------------------------------------------------- /Excel4Delphi.ExportHTML.pas: -------------------------------------------------------------------------------- 1 | unit Excel4Delphi.ExportHTML; 2 | 3 | interface 4 | 5 | uses 6 | Windows, 7 | SysUtils, 8 | UITypes, 9 | Types, 10 | Classes, 11 | Math, 12 | Graphics, 13 | AnsiStrings, 14 | Excel4Delphi, 15 | Excel4Delphi.Xml; 16 | 17 | type 18 | TZExportHTML = class(TZExport) 19 | public 20 | procedure ExportTo(AStream: TStream; ASheets: TArray; options: TExportOptions); override; 21 | end; 22 | 23 | implementation 24 | 25 | { TZExportHTML } 26 | 27 | procedure TZExportHTML.ExportTo(AStream: TStream; ASheets: TArray; options: TExportOptions); 28 | var xml: TZsspXMLWriterH; 29 | i, j, t, l, r: integer; 30 | NumTopLeft: integer; 31 | s, value, numformat: string; 32 | Att: TZAttributesH; 33 | max_width: Real; 34 | strArray: TArray; 35 | sheet: TZSheet; 36 | function HTMLStyleTable(name: string; const Style: TZStyle): string; 37 | var s: string; i, l: integer; 38 | begin 39 | result := #13#10 + ' .' + name + '{'#13#10; 40 | for i := 0 to 3 do begin 41 | s := 'border-'; 42 | l := 0; 43 | case i of 44 | 0: s := s + 'left:'; 45 | 1: s := s + 'top:'; 46 | 2: s := s + 'right:'; 47 | 3: s := s + 'bottom:'; 48 | end; 49 | s := s + '#' + ColorToHTMLHex(Style.Border[TZBordersPos(i)].Color); 50 | if Style.Border[TZBordersPos(i)].Weight <> 0 then 51 | s := s + ' ' + IntToStr(Style.Border[TZBordersPos(i)].Weight) + 'px' 52 | else 53 | inc(l); 54 | case Style.Border[TZBordersPos(i)].LineStyle of 55 | ZEContinuous: s := s + ' ' + 'solid'; 56 | ZEHair: s := s + ' ' + 'solid'; 57 | ZEDot: s := s + ' ' + 'dotted'; 58 | ZEDashDotDot: s := s + ' ' + 'dotted'; 59 | ZEDash: s := s + ' ' + 'dashed'; 60 | ZEDashDot: s := s + ' ' + 'dashed'; 61 | ZESlantDashDot: s := s + ' ' + 'dashed'; 62 | ZEDouble: s := s + ' ' + 'double'; 63 | else 64 | inc(l); 65 | end; 66 | s := s + ';'; 67 | if l <> 2 then 68 | result := result + s + #13#10; 69 | end; 70 | result := result + 'background:#' + ColorToHTMLHex(Style.BGColor) + ';}'; 71 | end; 72 | 73 | function HTMLStyleFont(name: string; const Style: TZStyle): string; 74 | begin 75 | result := #13#10 + ' .' + name + '{'#13#10; 76 | result := result + 'color:#' + ColorToHTMLHex(Style.Font.Color) + ';'; 77 | result := result + 'font-size:' + FloatToStr(Style.Font.Size, TFormatSettings.Invariant) + 'px;'; 78 | result := result + 'font-family:' + Style.Font.Name + ';}'; 79 | end; 80 | 81 | begin 82 | if Length(ASheets) = 0 then begin 83 | SetLength(ASheets, WorkBook.Sheets.Count); 84 | for I := 0 to WorkBook.Sheets.Count-1 do 85 | ASheets[i] := i; 86 | end; 87 | 88 | xml := TZsspXMLWriterH.Create(AStream); 89 | try 90 | xml.TabLength := 1; 91 | // start 92 | xml.Attributes.Clear(); 93 | xml.WriteRaw('', true, false); 94 | xml.WriteTagNode('HTML', true, true, false); 95 | xml.WriteTagNode('HEAD', true, true, false); 96 | xml.WriteTag('TITLE', WorkBook.Sheets[ASheets[0]].Title, true, false, false); 97 | 98 | //styles 99 | s := 'body {'; 100 | s := s + 'background:#' + ColorToHTMLHex(WorkBook.Styles.DefaultStyle.BGColor) + ';'; 101 | s := s + 'color:#' + ColorToHTMLHex(WorkBook.Styles.DefaultStyle.Font.Color) + ';'; 102 | s := s + 'font-size:' + FloatToStr(WorkBook.Styles.DefaultStyle.Font.Size, TFormatSettings.Invariant) + 'px;'; 103 | s := s + 'font-family:' + WorkBook.Styles.DefaultStyle.Font.Name + ';}'; 104 | 105 | s := s + HTMLStyleTable('T19', WorkBook.Styles.DefaultStyle); 106 | s := s + HTMLStyleFont('F19', WorkBook.Styles.DefaultStyle); 107 | 108 | for i := 0 to WorkBook.Styles.Count - 1 do begin 109 | s := s + HTMLStyleTable('T' + IntToStr(i + 20), WorkBook.Styles[i]); 110 | s := s + HTMLStyleFont('F' + IntToStr(i + 20), WorkBook.Styles[i]); 111 | end; 112 | 113 | xml.WriteTag('STYLE', s, true, true, false); 114 | xml.Attributes.Add('HTTP-EQUIV', 'CONTENT-TYPE'); 115 | xml.Attributes.Add('CONTENT', 'TEXT/HTML; CHARSET=UTF-8'); 116 | xml.WriteTag('META', '', true, false, false); 117 | xml.WriteEndTagNode(); // HEAD 118 | 119 | //BODY 120 | xml.Attributes.Clear(); 121 | xml.WriteTagNode('BODY', true, true, false); 122 | 123 | //Table 124 | for var si in ASheets do begin 125 | sheet := WorkBook.Sheets[si]; 126 | 127 | max_width := 0.0; 128 | for i := 0 to sheet.ColCount - 1 do 129 | max_width := max_width + sheet.ColWidths[i]; 130 | 131 | xml.Attributes.Clear(); 132 | xml.Attributes.Add('cellSpacing', '0'); 133 | xml.Attributes.Add('border', '0'); 134 | xml.Attributes.Add('width', FloatToStr(max_width).Replace(',', '.')); 135 | xml.WriteTagNode('TABLE', true, true, false); 136 | 137 | Att := TZAttributesH.Create(); 138 | Att.Clear(); 139 | for i := 0 to sheet.RowCount - 1 do begin 140 | xml.Attributes.Clear(); 141 | xml.Attributes.Add('height', floattostr(sheet.RowHeights[i]).Replace(',', '.')); 142 | xml.WriteTagNode('TR', true, true, true); 143 | xml.Attributes.Clear(); 144 | for j := 0 to sheet.ColCount - 1 do begin 145 | var cell := sheet.Cell[j ,i]; 146 | // если ячейка входит в объединённые области и не является 147 | // верхней левой ячейкой в этой области - пропускаем её 148 | if not cell.IsMerged() or cell.IsLeftTopMerged() then begin 149 | xml.Attributes.Clear(); 150 | NumTopLeft := sheet.MergeCells.InLeftTopCorner(j, i); 151 | if NumTopLeft >= 0 then begin 152 | t := sheet.MergeCells.Items[NumTopLeft].Right - sheet.MergeCells.Items[NumTopLeft].Left; 153 | if t > 0 then 154 | xml.Attributes.Add('colspan', InttOstr(t + 1)); 155 | t := sheet.MergeCells.Items[NumTopLeft].Bottom - sheet.MergeCells.Items[NumTopLeft].Top; 156 | if t > 0 then 157 | xml.Attributes.Add('rowspan', InttOstr(t + 1)); 158 | end; 159 | t := cell.CellStyle; 160 | if sheet.WorkBook.Styles[t].Alignment.Horizontal = ZHCenter then 161 | xml.Attributes.Add('align', 'center') 162 | else if sheet.WorkBook.Styles[t].Alignment.Horizontal = ZHRight then 163 | xml.Attributes.Add('align', 'right') 164 | else if sheet.WorkBook.Styles[t].Alignment.Horizontal = ZHJustify then 165 | xml.Attributes.Add('align', 'justify'); 166 | numformat := sheet.WorkBook.Styles[t].NumberFormat; 167 | xml.Attributes.Add('class', 'T' + IntToStr(t + 20)); 168 | xml.Attributes.Add('width', inttostr(sheet.Columns[j].WidthPix) + 'px'); 169 | 170 | xml.WriteTagNode('TD', true, false, false); 171 | xml.Attributes.Clear(); 172 | Att.Clear(); 173 | Att.Add('class', 'F' + IntToStr(t + 20)); 174 | if fsbold in sheet.WorkBook.Styles[t].Font.Style then 175 | xml.WriteTagNode('B', false, false, false); 176 | if fsItalic in sheet.WorkBook.Styles[t].Font.Style then 177 | xml.WriteTagNode('I', false, false, false); 178 | if fsUnderline in sheet.WorkBook.Styles[t].Font.Style then 179 | xml.WriteTagNode('U', false, false, false); 180 | if fsStrikeOut in sheet.WorkBook.Styles[t].Font.Style then 181 | xml.WriteTagNode('S', false, false, false); 182 | 183 | l := Length(cell.Href); 184 | if l > 0 then begin 185 | xml.Attributes.Add('href', cell.Href); 186 | //target? 187 | xml.WriteTagNode('A', false, false, false); 188 | xml.Attributes.Clear(); 189 | end; 190 | 191 | value := cell.Data; 192 | 193 | //value := value.Replace(#13#10, '
'); 194 | case cell.CellType of 195 | TZCellType.ZENumber: 196 | begin 197 | r := numformat.IndexOf('.'); 198 | if r > -1 then begin 199 | value := FloatToStrF(cell.AsDouble, ffNumber, 12, Min(4, Max(0, numformat.Substring(r).Length - 1))); 200 | end 201 | else begin 202 | value := FloatToStr(cell.AsDouble); 203 | end; 204 | end; 205 | TZCellType.ZEDateTime: 206 | begin 207 | // todo: make datetimeformat from cell NumberFormat 208 | value := FormatDateTime('dd.mm.yyyy', cell.AsDateTime); 209 | end; 210 | end; 211 | strArray := value.Split([#13, #10], TStringSplitOptions.ExcludeEmpty); 212 | for r := 0 to Length(strArray) - 1 do begin 213 | if r > 0 then 214 | xml.WriteTag('BR', ''); 215 | xml.WriteTag('FONT', strArray[r], Att, false, false, true); 216 | end; 217 | 218 | if l > 0 then 219 | xml.WriteEndTagNode(); // A 220 | 221 | if fsbold in sheet.WorkBook.Styles[t].Font.Style then 222 | xml.WriteEndTagNode(); // B 223 | if fsItalic in sheet.WorkBook.Styles[t].Font.Style then 224 | xml.WriteEndTagNode(); // I 225 | if fsUnderline in sheet.WorkBook.Styles[t].Font.Style then 226 | xml.WriteEndTagNode(); // U 227 | if fsStrikeOut in sheet.WorkBook.Styles[t].Font.Style then 228 | xml.WriteEndTagNode(); // S 229 | xml.WriteEndTagNode(); // TD 230 | end; 231 | 232 | end; 233 | xml.WriteEndTagNode(); // TR 234 | end; 235 | end; 236 | 237 | xml.WriteEndTagNode(); // BODY 238 | xml.WriteEndTagNode(); // HTML 239 | xml.EndSaveTo(); 240 | FreeAndNil(Att); 241 | finally 242 | xml.Free(); 243 | end; 244 | end; 245 | 246 | end. 247 | 248 | -------------------------------------------------------------------------------- /Excel4Delphi.Formula.pas: -------------------------------------------------------------------------------- 1 | unit Excel4Delphi.Formula; 2 | 3 | interface 4 | 5 | type 6 | TZEFormula = class 7 | /// 8 | /// Return absolute AA styled cell address. 9 | /// 10 | class function GetColAddres(const ColumnIndex: integer; FromZero: boolean = true): string; static; 11 | /// 12 | /// Extracts column index from it's AA address. 13 | /// 14 | class function GetColIndex(ColumnAdress: string; FromZero: boolean = true): integer; static; 15 | /// 16 | /// Extracts cell column and row from A1 styled address. 17 | /// 18 | class function GetCellCoords(const cell: string; out column, row: integer): boolean; static; 19 | /// 20 | /// Extracts range top, left right and bottom from 'А1:B2' based string. 21 | /// If string is 'A1' format then right=left, bottom=top. 22 | /// 23 | class function GetCellRange(const range: string; out left, top, right, bottom: integer): boolean; static; 24 | end; 25 | 26 | implementation 27 | 28 | uses 29 | SysUtils, Math; 30 | 31 | const 32 | CHARS: array [0..25] of char = ( 33 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 34 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' 35 | ); 36 | 37 | { TZEFormula } 38 | 39 | class function TZEFormula.GetColAddres(const columnIndex: integer; FromZero: boolean): string; 40 | var t, n: integer; s: string; 41 | begin 42 | t := columnIndex; 43 | if (not FromZero) then 44 | dec(t); 45 | result := ''; 46 | s := ''; 47 | while t >= 0 do begin 48 | n := t mod 26; 49 | t := (t div 26) - 1; 50 | s := s + CHARS[n]; 51 | end; 52 | for t := length(s) downto 1 do 53 | result := result + s[t]; 54 | end; 55 | 56 | class function TZEFormula.GetColIndex(ColumnAdress: string; FromZero: boolean): integer; 57 | var i: integer; num, t, s: integer; 58 | begin 59 | result := -1; 60 | num := 0; 61 | ColumnAdress := UpperCase(ColumnAdress); 62 | s := 1; 63 | for i := length(ColumnAdress) downto 1 do begin 64 | if not CharInSet(ColumnAdress[I], ['A'..'Z']) then 65 | continue; 66 | t := ord(ColumnAdress[i]) - ord('A'); 67 | num := num + (t + 1) * s; 68 | s := s * 26; 69 | if (s < 0) or (num < 0) then 70 | exit; 71 | end; 72 | result := num; 73 | if FromZero then 74 | result := result - 1; 75 | end; 76 | 77 | class function TZEFormula.GetCellCoords(const cell: string; out column, row: integer): boolean; 78 | var right, bottom: integer; 79 | begin 80 | result := GetCellRange(cell, column, row, right, bottom); 81 | end; 82 | 83 | class function TZEFormula.GetCellRange(const range: string; out left, top, right, bottom: integer): boolean; 84 | var i, p: integer; 85 | cols, rows: TArray; 86 | begin 87 | left := -1; top := -1; right := -1; bottom := -1; 88 | cols := ['','']; 89 | rows := ['','']; 90 | result := true; 91 | p := 0; 92 | for i := 1 to length(range) do 93 | case range[i] of 94 | 'A'..'Z', 'a'..'z': 95 | cols[p] := cols[p] + range[i]; 96 | '0'..'9': 97 | begin 98 | if cols[p] = '' then 99 | exit(false); 100 | rows[p] := rows[p] + range[i]; 101 | end; 102 | ':': 103 | if p = 0 then 104 | inc(p) 105 | else 106 | exit(false); 107 | else 108 | exit(false); 109 | end; 110 | 111 | if not TryStrToInt(rows[0], top) then 112 | exit(false); 113 | 114 | left := GetColIndex(cols[0]); 115 | if left < 0 then 116 | exit(false); 117 | 118 | bottom := Max(StrToIntDef(rows[1], -1), top); 119 | right := Max(GetColIndex(cols[1]), left); 120 | dec(top); 121 | dec(bottom); 122 | end; 123 | 124 | end. 125 | -------------------------------------------------------------------------------- /Excel4Delphi.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {ABBD4AC5-16F9-4DC6-99CB-777BA781C3EF} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Default.Personality.12 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Excel4DelphiLib.dpk: -------------------------------------------------------------------------------- 1 | package Excel4DelphiLib; 2 | 3 | {$R *.res} 4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 5 | {$ALIGN 8} 6 | {$ASSERTIONS ON} 7 | {$BOOLEVAL OFF} 8 | {$DEBUGINFO OFF} 9 | {$EXTENDEDSYNTAX ON} 10 | {$IMPORTEDDATA ON} 11 | {$IOCHECKS ON} 12 | {$LOCALSYMBOLS ON} 13 | {$LONGSTRINGS ON} 14 | {$OPENSTRINGS ON} 15 | {$OPTIMIZATION OFF} 16 | {$OVERFLOWCHECKS OFF} 17 | {$RANGECHECKS OFF} 18 | {$REFERENCEINFO ON} 19 | {$SAFEDIVIDE OFF} 20 | {$STACKFRAMES ON} 21 | {$TYPEDADDRESS OFF} 22 | {$VARSTRINGCHECKS ON} 23 | {$WRITEABLECONST ON} 24 | {$MINENUMSIZE 1} 25 | {$IMAGEBASE $400000} 26 | {$DEFINE DEBUG} 27 | {$ENDIF IMPLICITBUILDING} 28 | {$DESCRIPTION 'Excel4Delphi component'} 29 | {$IMPLICITBUILD ON} 30 | 31 | requires 32 | vcl; 33 | 34 | contains 35 | Excel4Delphi in 'Excel4Delphi.pas', 36 | Excel4Delphi.Stream in 'Excel4Delphi.Stream.pas', 37 | Excel4Delphi.Xml in 'Excel4Delphi.Xml.pas', 38 | Excel4Delphi.Common in 'Excel4Delphi.Common.pas', 39 | Excel4Delphi.Formula in 'Excel4Delphi.Formula.pas', 40 | Excel4Delphi.ExportHTML in 'Excel4Delphi.ExportHTML.pas', 41 | Excel4Delphi.NumberFormat in 'Excel4Delphi.NumberFormat.pas', 42 | Excel4Delphi.XlsxStream in 'Excel4Delphi.XlsxStream.pas'; 43 | 44 | end. 45 | -------------------------------------------------------------------------------- /Excel4DelphiLib.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {3CC3B766-2D13-4B54-8E0D-A3D82AD28218} 4 | Excel4DelphiLib.dpk 5 | True 6 | Debug 7 | 3 8 | Package 9 | VCL 10 | 19.4 11 | Win64 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Cfg_1 34 | true 35 | true 36 | 37 | 38 | true 39 | Cfg_1 40 | true 41 | true 42 | 43 | 44 | true 45 | Base 46 | true 47 | 48 | 49 | true 50 | Cfg_2 51 | true 52 | true 53 | 54 | 55 | true 56 | Cfg_2 57 | true 58 | true 59 | 60 | 61 | true 62 | false 63 | 00400000 64 | 1049 65 | false 66 | true 67 | false 68 | Excel4Delphi component 69 | false 70 | false 71 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) 72 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 73 | true 74 | Excel4DelphiLib 75 | .\$(Platform)\$(Config) 76 | .\$(Platform)\$(Config) 77 | .\$(Platform)\$(Config) 78 | 79 | 80 | System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 81 | 1033 82 | true 83 | vcl;Jcl;$(DCC_UsePackage) 84 | 85 | 86 | vcl;$(DCC_UsePackage) 87 | System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 88 | Debug 89 | true 90 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 91 | 1033 92 | 93 | 94 | 0 95 | 0 96 | RELEASE;$(DCC_Define) 97 | false 98 | 99 | 100 | true 101 | 1033 102 | 103 | 104 | true 105 | 1033 106 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 107 | 108 | 109 | true 110 | DEBUG;$(DCC_Define) 111 | false 112 | 113 | 114 | true 115 | 1033 116 | 117 | 118 | true 119 | 1033 120 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 121 | 122 | 123 | 124 | MainSource 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | Base 137 | 138 | 139 | Cfg_1 140 | Base 141 | 142 | 143 | Cfg_2 144 | Base 145 | 146 | 147 | 148 | Delphi.Personality.12 149 | Package 150 | 151 | 152 | 153 | Excel4DelphiLib.dpk 154 | 155 | 156 | True 157 | False 158 | 1 159 | 0 160 | 0 161 | 0 162 | False 163 | False 164 | False 165 | False 166 | False 167 | 1049 168 | 1251 169 | 170 | 171 | 172 | 173 | 1.0.0.0 174 | 175 | 176 | 177 | 178 | 179 | 1.0.0.0 180 | 181 | 182 | 183 | Microsoft Office 2000 Sample Automation Server Wrapper Components 184 | Microsoft Office XP Sample Automation Server Wrapper Components 185 | 186 | 187 | 188 | True 189 | True 190 | 191 | 192 | 193 | 194 | Excel4DelphiLib.bpl 195 | true 196 | 197 | 198 | 199 | 200 | 1 201 | 202 | 203 | 0 204 | 205 | 206 | 207 | 208 | classes 209 | 64 210 | 211 | 212 | classes 213 | 64 214 | 215 | 216 | 217 | 218 | res\xml 219 | 1 220 | 221 | 222 | res\xml 223 | 1 224 | 225 | 226 | 227 | 228 | library\lib\armeabi-v7a 229 | 1 230 | 231 | 232 | 233 | 234 | library\lib\armeabi 235 | 1 236 | 237 | 238 | library\lib\armeabi 239 | 1 240 | 241 | 242 | 243 | 244 | library\lib\armeabi-v7a 245 | 1 246 | 247 | 248 | 249 | 250 | library\lib\mips 251 | 1 252 | 253 | 254 | library\lib\mips 255 | 1 256 | 257 | 258 | 259 | 260 | library\lib\armeabi-v7a 261 | 1 262 | 263 | 264 | library\lib\arm64-v8a 265 | 1 266 | 267 | 268 | 269 | 270 | library\lib\armeabi-v7a 271 | 1 272 | 273 | 274 | 275 | 276 | res\drawable 277 | 1 278 | 279 | 280 | res\drawable 281 | 1 282 | 283 | 284 | 285 | 286 | res\values 287 | 1 288 | 289 | 290 | res\values 291 | 1 292 | 293 | 294 | 295 | 296 | res\values-v21 297 | 1 298 | 299 | 300 | res\values-v21 301 | 1 302 | 303 | 304 | 305 | 306 | res\values 307 | 1 308 | 309 | 310 | res\values 311 | 1 312 | 313 | 314 | 315 | 316 | res\drawable 317 | 1 318 | 319 | 320 | res\drawable 321 | 1 322 | 323 | 324 | 325 | 326 | res\drawable-xxhdpi 327 | 1 328 | 329 | 330 | res\drawable-xxhdpi 331 | 1 332 | 333 | 334 | 335 | 336 | res\drawable-xxxhdpi 337 | 1 338 | 339 | 340 | res\drawable-xxxhdpi 341 | 1 342 | 343 | 344 | 345 | 346 | res\drawable-ldpi 347 | 1 348 | 349 | 350 | res\drawable-ldpi 351 | 1 352 | 353 | 354 | 355 | 356 | res\drawable-mdpi 357 | 1 358 | 359 | 360 | res\drawable-mdpi 361 | 1 362 | 363 | 364 | 365 | 366 | res\drawable-hdpi 367 | 1 368 | 369 | 370 | res\drawable-hdpi 371 | 1 372 | 373 | 374 | 375 | 376 | res\drawable-xhdpi 377 | 1 378 | 379 | 380 | res\drawable-xhdpi 381 | 1 382 | 383 | 384 | 385 | 386 | res\drawable-mdpi 387 | 1 388 | 389 | 390 | res\drawable-mdpi 391 | 1 392 | 393 | 394 | 395 | 396 | res\drawable-hdpi 397 | 1 398 | 399 | 400 | res\drawable-hdpi 401 | 1 402 | 403 | 404 | 405 | 406 | res\drawable-xhdpi 407 | 1 408 | 409 | 410 | res\drawable-xhdpi 411 | 1 412 | 413 | 414 | 415 | 416 | res\drawable-xxhdpi 417 | 1 418 | 419 | 420 | res\drawable-xxhdpi 421 | 1 422 | 423 | 424 | 425 | 426 | res\drawable-xxxhdpi 427 | 1 428 | 429 | 430 | res\drawable-xxxhdpi 431 | 1 432 | 433 | 434 | 435 | 436 | res\drawable-small 437 | 1 438 | 439 | 440 | res\drawable-small 441 | 1 442 | 443 | 444 | 445 | 446 | res\drawable-normal 447 | 1 448 | 449 | 450 | res\drawable-normal 451 | 1 452 | 453 | 454 | 455 | 456 | res\drawable-large 457 | 1 458 | 459 | 460 | res\drawable-large 461 | 1 462 | 463 | 464 | 465 | 466 | res\drawable-xlarge 467 | 1 468 | 469 | 470 | res\drawable-xlarge 471 | 1 472 | 473 | 474 | 475 | 476 | res\values 477 | 1 478 | 479 | 480 | res\values 481 | 1 482 | 483 | 484 | 485 | 486 | 1 487 | 488 | 489 | 1 490 | 491 | 492 | 0 493 | 494 | 495 | 496 | 497 | 1 498 | .framework 499 | 500 | 501 | 1 502 | .framework 503 | 504 | 505 | 1 506 | .framework 507 | 508 | 509 | 0 510 | 511 | 512 | 513 | 514 | 1 515 | .dylib 516 | 517 | 518 | 1 519 | .dylib 520 | 521 | 522 | 1 523 | .dylib 524 | 525 | 526 | 0 527 | .dll;.bpl 528 | 529 | 530 | 531 | 532 | 1 533 | .dylib 534 | 535 | 536 | 1 537 | .dylib 538 | 539 | 540 | 1 541 | .dylib 542 | 543 | 544 | 1 545 | .dylib 546 | 547 | 548 | 1 549 | .dylib 550 | 551 | 552 | 1 553 | .dylib 554 | 555 | 556 | 0 557 | .bpl 558 | 559 | 560 | 561 | 562 | 0 563 | 564 | 565 | 0 566 | 567 | 568 | 0 569 | 570 | 571 | 0 572 | 573 | 574 | 0 575 | 576 | 577 | 0 578 | 579 | 580 | 0 581 | 582 | 583 | 0 584 | 585 | 586 | 0 587 | 588 | 589 | 590 | 591 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 592 | 1 593 | 594 | 595 | 596 | 597 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 598 | 1 599 | 600 | 601 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 602 | 1 603 | 604 | 605 | 606 | 607 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 608 | 1 609 | 610 | 611 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 612 | 1 613 | 614 | 615 | 616 | 617 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 618 | 1 619 | 620 | 621 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 622 | 1 623 | 624 | 625 | 626 | 627 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 628 | 1 629 | 630 | 631 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 632 | 1 633 | 634 | 635 | 636 | 637 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 638 | 1 639 | 640 | 641 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 642 | 1 643 | 644 | 645 | 646 | 647 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 648 | 1 649 | 650 | 651 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 652 | 1 653 | 654 | 655 | 656 | 657 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 658 | 1 659 | 660 | 661 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 662 | 1 663 | 664 | 665 | 666 | 667 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 668 | 1 669 | 670 | 671 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 672 | 1 673 | 674 | 675 | 676 | 677 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 678 | 1 679 | 680 | 681 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 682 | 1 683 | 684 | 685 | 686 | 687 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 688 | 1 689 | 690 | 691 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 692 | 1 693 | 694 | 695 | 696 | 697 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 698 | 1 699 | 700 | 701 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 702 | 1 703 | 704 | 705 | 706 | 707 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 708 | 1 709 | 710 | 711 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 712 | 1 713 | 714 | 715 | 716 | 717 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 718 | 1 719 | 720 | 721 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 722 | 1 723 | 724 | 725 | 726 | 727 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 728 | 1 729 | 730 | 731 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 732 | 1 733 | 734 | 735 | 736 | 737 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 738 | 1 739 | 740 | 741 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 742 | 1 743 | 744 | 745 | 746 | 747 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 748 | 1 749 | 750 | 751 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 752 | 1 753 | 754 | 755 | 756 | 757 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 758 | 1 759 | 760 | 761 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 762 | 1 763 | 764 | 765 | 766 | 767 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 768 | 1 769 | 770 | 771 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 772 | 1 773 | 774 | 775 | 776 | 777 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 778 | 1 779 | 780 | 781 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 782 | 1 783 | 784 | 785 | 786 | 787 | 1 788 | 789 | 790 | 1 791 | 792 | 793 | 794 | 795 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 796 | 1 797 | 798 | 799 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 800 | 1 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 1 809 | 810 | 811 | 1 812 | 813 | 814 | 1 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | Contents\Resources 823 | 1 824 | 825 | 826 | Contents\Resources 827 | 1 828 | 829 | 830 | Contents\Resources 831 | 1 832 | 833 | 834 | 835 | 836 | library\lib\armeabi-v7a 837 | 1 838 | 839 | 840 | library\lib\arm64-v8a 841 | 1 842 | 843 | 844 | 1 845 | 846 | 847 | 1 848 | 849 | 850 | 1 851 | 852 | 853 | 1 854 | 855 | 856 | 1 857 | 858 | 859 | 1 860 | 861 | 862 | 1 863 | 864 | 865 | 0 866 | 867 | 868 | 869 | 870 | library\lib\armeabi-v7a 871 | 1 872 | 873 | 874 | 875 | 876 | 1 877 | 878 | 879 | 1 880 | 881 | 882 | 883 | 884 | Assets 885 | 1 886 | 887 | 888 | Assets 889 | 1 890 | 891 | 892 | 893 | 894 | Assets 895 | 1 896 | 897 | 898 | Assets 899 | 1 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 12 916 | 917 | 918 | 919 | 920 | 921 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Ruslan Neborak 2 | 3 | Read/write xlsx (Office Open XML file format (Spreadsheet)) 4 | Author: Ruslan V. Neborak 5 | e-mail: avemey@tut.by 6 | URL: http://avemey.com 7 | License: zlib 8 | Last update: 2016.07.03 9 | 10 | This software is provided 'as-is', without any express or implied 11 | warranty. In no event will the authors be held liable for any damages 12 | arising from the use of this software. 13 | 14 | Permission is granted to anyone to use this software for any purpose, 15 | including commercial applications, and to alter it and redistribute it 16 | freely, subject to the following restrictions: 17 | 18 | 1. The origin of this software must not be misrepresented; you must not 19 | claim that you wrote the original software. If you use this software 20 | in a product, an acknowledgment in the product documentation would be 21 | appreciated but is not required. 22 | 23 | 2. Altered source versions must be plainly marked as such, and must not be 24 | misrepresented as being the original software. 25 | 26 | 3. This notice may not be removed or altered from any source 27 | distribution. -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | 2 | # Excel4Delphi 3 | Read, Write excel 2002/2003 XML (SpreadsheetML / XML Spreadsheet) library. 4 | 5 | fork from https://github.com/Avemey/zexmlss 6 | 7 | ## Exchamples 8 | 9 | ```pas 10 | // Creating new workbook 11 | var workBook: TZWorkBook; 12 | ... 13 | workBook := TZWorkBook.Create(); 14 | try 15 | workBook.Sheets.Add('My sheet'); 16 | workBook.Sheets[0].ColCount := 10; 17 | workBook.Sheets[0].RowCount := 10; 18 | workBook.Sheets[0].CellRef['A', 0].AsString := 'Hello'; 19 | workBook.Sheets[0].RangeRef['A', 0, 'B', 2].Merge(); 20 | workBook.SaveToFile('file.xlsx'); 21 | finally 22 | workBook.Free(); 23 | end 24 | ``` 25 | 26 | ```pas 27 | // Editing exists workbook 28 | var workBook: TZWorkBook; 29 | ... 30 | workBook := TZWorkBook.Create(); 31 | try 32 | workBook.LoadFromFile('file.xlsx'); 33 | workBook.Sheets[0].CellRef['A', 0].AsString := 'Hello'; 34 | workBook.Sheets[0].CellRef['A', 0].FontStyle := [fsBold]; 35 | workBook.SaveToFile('file.xlsx'); 36 | finally 37 | workBook.Free(); 38 | end 39 | ``` -------------------------------------------------------------------------------- /Test/Examples/Test1.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konctantin/Excel4Delphi/e5fabdc7d9d0f4344b79d0b59b410c92c18c421b/Test/Examples/Test1.xlsx -------------------------------------------------------------------------------- /Test/Excel4DelphiLibTest.dpr: -------------------------------------------------------------------------------- 1 | program Excel4DelphiLibTest; 2 | 3 | {$IFNDEF TESTINSIGHT} 4 | {$APPTYPE CONSOLE} 5 | {$ENDIF} 6 | {$STRONGLINKTYPES ON} 7 | uses 8 | System.SysUtils, 9 | {$IFDEF TESTINSIGHT} 10 | TestInsight.DUnitX, 11 | {$ELSE} 12 | DUnitX.Loggers.Console, 13 | DUnitX.Loggers.Xml.NUnit, 14 | {$ENDIF } 15 | DUnitX.TestFramework, 16 | Excel4DelphiTest in 'Excel4DelphiTest.pas', 17 | Excel4DelphiTest.Converters in 'Excel4DelphiTest.Converters.pas', 18 | Excel4DelphiTest.Formula in 'Excel4DelphiTest.Formula.pas'; 19 | 20 | {$IFNDEF TESTINSIGHT} 21 | var 22 | runner: ITestRunner; 23 | results: IRunResults; 24 | logger: ITestLogger; 25 | nunitLogger : ITestLogger; 26 | {$ENDIF} 27 | begin 28 | {$IFDEF TESTINSIGHT} 29 | TestInsight.DUnitX.RunRegisteredTests; 30 | {$ELSE} 31 | try 32 | //Check command line options, will exit if invalid 33 | TDUnitX.CheckCommandLine; 34 | //Create the test runner 35 | runner := TDUnitX.CreateRunner; 36 | //Tell the runner to use RTTI to find Fixtures 37 | runner.UseRTTI := True; 38 | //When true, Assertions must be made during tests; 39 | runner.FailsOnNoAsserts := False; 40 | 41 | //tell the runner how we will log things 42 | //Log to the console window if desired 43 | if TDUnitX.Options.ConsoleMode <> TDunitXConsoleMode.Off then 44 | begin 45 | logger := TDUnitXConsoleLogger.Create(TDUnitX.Options.ConsoleMode = TDunitXConsoleMode.Quiet); 46 | runner.AddLogger(logger); 47 | end; 48 | //Generate an NUnit compatible XML File 49 | nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); 50 | runner.AddLogger(nunitLogger); 51 | 52 | //Run tests 53 | results := runner.Execute; 54 | if not results.AllPassed then 55 | System.ExitCode := EXIT_ERRORS; 56 | 57 | {$IFNDEF CI} 58 | //We don't want this happening when running under CI. 59 | if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then 60 | begin 61 | System.Write('Done.. press key to quit.'); 62 | System.Readln; 63 | end; 64 | {$ENDIF} 65 | except 66 | on E: Exception do 67 | System.Writeln(E.ClassName, ': ', E.Message); 68 | end; 69 | {$ENDIF} 70 | end. 71 | -------------------------------------------------------------------------------- /Test/Excel4DelphiLibTest.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {38ED5A10-CBF1-473A-81F7-A909A4CD676D} 4 | 19.4 5 | None 6 | True 7 | Debug 8 | Win32 9 | 1 10 | Console 11 | Excel4DelphiLibTest.dpr 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Base 34 | true 35 | 36 | 37 | true 38 | Base 39 | true 40 | 41 | 42 | true 43 | Base 44 | true 45 | 46 | 47 | true 48 | Base 49 | true 50 | 51 | 52 | true 53 | Base 54 | true 55 | 56 | 57 | true 58 | Cfg_1 59 | true 60 | true 61 | 62 | 63 | true 64 | Base 65 | true 66 | 67 | 68 | .\$(Platform)\$(Config) 69 | .\$(Platform)\$(Config) 70 | false 71 | false 72 | false 73 | false 74 | false 75 | System;Xml;Data;Datasnap;Web;Soap;Vcl;$(DCC_Namespace) 76 | true 77 | $(BDS)\bin\delphi_PROJECTICON.ico 78 | $(BDS)\bin\delphi_PROJECTICNS.icns 79 | $(DUnitX);..\;$(DCC_UnitSearchPath) 80 | Excel4DelphiLibTest 81 | 1049 82 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 83 | 84 | 85 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= 86 | Debug 87 | annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar 88 | 89 | 90 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= 91 | Debug 92 | annotation-1.2.0.dex.jar;asynclayoutinflater-1.0.0.dex.jar;billing-4.0.0.dex.jar;browser-1.0.0.dex.jar;cloud-messaging.dex.jar;collection-1.0.0.dex.jar;coordinatorlayout-1.0.0.dex.jar;core-1.5.0-rc02.dex.jar;core-common-2.0.1.dex.jar;core-runtime-2.0.1.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;firebase-annotations-16.0.0.dex.jar;firebase-common-20.0.0.dex.jar;firebase-components-17.0.0.dex.jar;firebase-datatransport-18.0.0.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.0.0.dex.jar;firebase-installations-interop-17.0.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-22.0.0.dex.jar;fmx.dex.jar;fragment-1.0.0.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;legacy-support-core-ui-1.0.0.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.0.0.dex.jar;lifecycle-livedata-2.0.0.dex.jar;lifecycle-livedata-core-2.0.0.dex.jar;lifecycle-runtime-2.0.0.dex.jar;lifecycle-service-2.0.0.dex.jar;lifecycle-viewmodel-2.0.0.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;play-services-ads-20.1.0.dex.jar;play-services-ads-base-20.1.0.dex.jar;play-services-ads-identifier-17.0.0.dex.jar;play-services-ads-lite-20.1.0.dex.jar;play-services-base-17.5.0.dex.jar;play-services-basement-17.6.0.dex.jar;play-services-cloud-messaging-16.0.0.dex.jar;play-services-drive-17.0.0.dex.jar;play-services-games-21.0.0.dex.jar;play-services-location-18.0.0.dex.jar;play-services-maps-17.0.1.dex.jar;play-services-measurement-base-18.0.0.dex.jar;play-services-measurement-sdk-api-18.0.0.dex.jar;play-services-places-placereport-17.0.0.dex.jar;play-services-stats-17.0.0.dex.jar;play-services-tasks-17.2.0.dex.jar;print-1.0.0.dex.jar;room-common-2.1.0.dex.jar;room-runtime-2.1.0.dex.jar;slidingpanelayout-1.0.0.dex.jar;sqlite-2.0.1.dex.jar;sqlite-framework-2.0.1.dex.jar;swiperefreshlayout-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.0.0.dex.jar;transport-runtime-3.0.0.dex.jar;user-messaging-platform-1.0.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.1.0.dex.jar 93 | 94 | 95 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 96 | iPhoneAndiPad 97 | true 98 | Debug 99 | $(MSBuildProjectName) 100 | 101 | 102 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 103 | Debug 104 | 105 | 106 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers 107 | Debug 108 | 109 | 110 | DataSnapServer;vclwinx;emshosting;fmx;DbxCommonDriver;vclie;bindengine;VCLRESTComponents;FireDACCommonODBC;DBXMSSQLDriver;IndyIPCommon;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;EhLib280;frxe28;dbxcds;vcledge;IndyIPClient;frxTee28;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;tmsexdXE14;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;fmxase;vcltouch;frx28;ExlReportRT_D28;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FireDACDBXDriver;tmsdXE14;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;tmsxlsdXE14;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;frxDB28;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;vcldb;ibxbindings;tmswizdXE14;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;adortl;dsnapxml;IndyIPServer;DataSnapClient;DataSnapProviderClient;dsnapcon;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;EhLibADODataDrivers280;ibxpress;bindcompvcl;dsnap;DBXSybaseASADriver;CloudService;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;DataSnapNativeClient;bindcompvclsmp;fmxobj;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 111 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 112 | Debug 113 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 114 | 1033 115 | 116 | 117 | DataSnapServer;vclwinx;emshosting;fmx;DbxCommonDriver;vclie;bindengine;VCLRESTComponents;FireDACCommonODBC;DBXMSSQLDriver;IndyIPCommon;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;dbxcds;vcledge;IndyIPClient;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;tmsexdXE14;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;fmxase;vcltouch;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FireDACDBXDriver;tmsdXE14;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;adortl;dsnapxml;IndyIPServer;DataSnapClient;DataSnapProviderClient;dsnapcon;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;EhLibADODataDrivers280;ibxpress;bindcompvcl;dsnap;DBXSybaseASADriver;CloudService;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;DataSnapNativeClient;bindcompvclsmp;fmxobj;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 118 | 119 | 120 | DEBUG;$(DCC_Define) 121 | true 122 | false 123 | true 124 | true 125 | true 126 | true 127 | true 128 | 129 | 130 | false 131 | 1033 132 | (None) 133 | none 134 | 135 | 136 | false 137 | RELEASE;$(DCC_Define) 138 | 0 139 | 0 140 | 141 | 142 | 143 | MainSource 144 | 145 | 146 | 147 | 148 | 149 | Base 150 | 151 | 152 | Cfg_1 153 | Base 154 | 155 | 156 | Cfg_2 157 | Base 158 | 159 | 160 | 161 | Delphi.Personality.12 162 | Application 163 | 164 | 165 | 166 | Excel4DelphiLibTest.dpr 167 | 168 | 169 | File C:\Users\Public\Documents\Embarcadero\Studio\22.0\Bpl\pckColorVisualizer.bpl not found 170 | File C:\Users\Public\Documents\Embarcadero\Studio\22.0\Bpl\ImageVisualizersPkgD13.bpl not found 171 | File C:\Users\Public\Documents\Embarcadero\Studio\22.0\Bpl\TDataSetVisualizer.bpl not found 172 | Microsoft Office 2000 Sample Automation Server Wrapper Components 173 | Microsoft Office XP Sample Automation Server Wrapper Components 174 | TMS VCL UI Pack 175 | TMS VCL UI Pack Extra 176 | TMS VCL UI Pack design time support 177 | TMS VCL UI Pack Wizards 178 | TMS TAdvStringGrid Excel support 179 | 180 | 181 | 182 | 183 | 184 | true 185 | 186 | 187 | 188 | 189 | true 190 | 191 | 192 | 193 | 194 | true 195 | 196 | 197 | 198 | 199 | Excel4DelphiLibTest.exe 200 | true 201 | 202 | 203 | 204 | 205 | 1 206 | 207 | 208 | Contents\MacOS 209 | 1 210 | 211 | 212 | 0 213 | 214 | 215 | 216 | 217 | classes 218 | 64 219 | 220 | 221 | classes 222 | 64 223 | 224 | 225 | 226 | 227 | res\xml 228 | 1 229 | 230 | 231 | res\xml 232 | 1 233 | 234 | 235 | 236 | 237 | library\lib\armeabi-v7a 238 | 1 239 | 240 | 241 | 242 | 243 | library\lib\armeabi 244 | 1 245 | 246 | 247 | library\lib\armeabi 248 | 1 249 | 250 | 251 | 252 | 253 | library\lib\armeabi-v7a 254 | 1 255 | 256 | 257 | 258 | 259 | library\lib\mips 260 | 1 261 | 262 | 263 | library\lib\mips 264 | 1 265 | 266 | 267 | 268 | 269 | library\lib\armeabi-v7a 270 | 1 271 | 272 | 273 | library\lib\arm64-v8a 274 | 1 275 | 276 | 277 | 278 | 279 | library\lib\armeabi-v7a 280 | 1 281 | 282 | 283 | 284 | 285 | res\drawable 286 | 1 287 | 288 | 289 | res\drawable 290 | 1 291 | 292 | 293 | 294 | 295 | res\values 296 | 1 297 | 298 | 299 | res\values 300 | 1 301 | 302 | 303 | 304 | 305 | res\values-v21 306 | 1 307 | 308 | 309 | res\values-v21 310 | 1 311 | 312 | 313 | 314 | 315 | res\values 316 | 1 317 | 318 | 319 | res\values 320 | 1 321 | 322 | 323 | 324 | 325 | res\drawable 326 | 1 327 | 328 | 329 | res\drawable 330 | 1 331 | 332 | 333 | 334 | 335 | res\drawable-xxhdpi 336 | 1 337 | 338 | 339 | res\drawable-xxhdpi 340 | 1 341 | 342 | 343 | 344 | 345 | res\drawable-xxxhdpi 346 | 1 347 | 348 | 349 | res\drawable-xxxhdpi 350 | 1 351 | 352 | 353 | 354 | 355 | res\drawable-ldpi 356 | 1 357 | 358 | 359 | res\drawable-ldpi 360 | 1 361 | 362 | 363 | 364 | 365 | res\drawable-mdpi 366 | 1 367 | 368 | 369 | res\drawable-mdpi 370 | 1 371 | 372 | 373 | 374 | 375 | res\drawable-hdpi 376 | 1 377 | 378 | 379 | res\drawable-hdpi 380 | 1 381 | 382 | 383 | 384 | 385 | res\drawable-xhdpi 386 | 1 387 | 388 | 389 | res\drawable-xhdpi 390 | 1 391 | 392 | 393 | 394 | 395 | res\drawable-mdpi 396 | 1 397 | 398 | 399 | res\drawable-mdpi 400 | 1 401 | 402 | 403 | 404 | 405 | res\drawable-hdpi 406 | 1 407 | 408 | 409 | res\drawable-hdpi 410 | 1 411 | 412 | 413 | 414 | 415 | res\drawable-xhdpi 416 | 1 417 | 418 | 419 | res\drawable-xhdpi 420 | 1 421 | 422 | 423 | 424 | 425 | res\drawable-xxhdpi 426 | 1 427 | 428 | 429 | res\drawable-xxhdpi 430 | 1 431 | 432 | 433 | 434 | 435 | res\drawable-xxxhdpi 436 | 1 437 | 438 | 439 | res\drawable-xxxhdpi 440 | 1 441 | 442 | 443 | 444 | 445 | res\drawable-small 446 | 1 447 | 448 | 449 | res\drawable-small 450 | 1 451 | 452 | 453 | 454 | 455 | res\drawable-normal 456 | 1 457 | 458 | 459 | res\drawable-normal 460 | 1 461 | 462 | 463 | 464 | 465 | res\drawable-large 466 | 1 467 | 468 | 469 | res\drawable-large 470 | 1 471 | 472 | 473 | 474 | 475 | res\drawable-xlarge 476 | 1 477 | 478 | 479 | res\drawable-xlarge 480 | 1 481 | 482 | 483 | 484 | 485 | res\values 486 | 1 487 | 488 | 489 | res\values 490 | 1 491 | 492 | 493 | 494 | 495 | 1 496 | 497 | 498 | Contents\MacOS 499 | 1 500 | 501 | 502 | 0 503 | 504 | 505 | 506 | 507 | Contents\MacOS 508 | 1 509 | .framework 510 | 511 | 512 | Contents\MacOS 513 | 1 514 | .framework 515 | 516 | 517 | Contents\MacOS 518 | 1 519 | .framework 520 | 521 | 522 | 0 523 | 524 | 525 | 526 | 527 | 1 528 | .dylib 529 | 530 | 531 | 1 532 | .dylib 533 | 534 | 535 | 1 536 | .dylib 537 | 538 | 539 | Contents\MacOS 540 | 1 541 | .dylib 542 | 543 | 544 | Contents\MacOS 545 | 1 546 | .dylib 547 | 548 | 549 | Contents\MacOS 550 | 1 551 | .dylib 552 | 553 | 554 | 0 555 | .dll;.bpl 556 | 557 | 558 | 559 | 560 | 1 561 | .dylib 562 | 563 | 564 | 1 565 | .dylib 566 | 567 | 568 | 1 569 | .dylib 570 | 571 | 572 | Contents\MacOS 573 | 1 574 | .dylib 575 | 576 | 577 | Contents\MacOS 578 | 1 579 | .dylib 580 | 581 | 582 | Contents\MacOS 583 | 1 584 | .dylib 585 | 586 | 587 | 0 588 | .bpl 589 | 590 | 591 | 592 | 593 | 0 594 | 595 | 596 | 0 597 | 598 | 599 | 0 600 | 601 | 602 | 0 603 | 604 | 605 | 0 606 | 607 | 608 | Contents\Resources\StartUp\ 609 | 0 610 | 611 | 612 | Contents\Resources\StartUp\ 613 | 0 614 | 615 | 616 | Contents\Resources\StartUp\ 617 | 0 618 | 619 | 620 | 0 621 | 622 | 623 | 624 | 625 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 626 | 1 627 | 628 | 629 | 630 | 631 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 632 | 1 633 | 634 | 635 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 636 | 1 637 | 638 | 639 | 640 | 641 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 642 | 1 643 | 644 | 645 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 646 | 1 647 | 648 | 649 | 650 | 651 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 652 | 1 653 | 654 | 655 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 656 | 1 657 | 658 | 659 | 660 | 661 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 662 | 1 663 | 664 | 665 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 666 | 1 667 | 668 | 669 | 670 | 671 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 672 | 1 673 | 674 | 675 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 676 | 1 677 | 678 | 679 | 680 | 681 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 682 | 1 683 | 684 | 685 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 686 | 1 687 | 688 | 689 | 690 | 691 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 692 | 1 693 | 694 | 695 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 696 | 1 697 | 698 | 699 | 700 | 701 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 702 | 1 703 | 704 | 705 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 706 | 1 707 | 708 | 709 | 710 | 711 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 712 | 1 713 | 714 | 715 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 716 | 1 717 | 718 | 719 | 720 | 721 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 722 | 1 723 | 724 | 725 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 726 | 1 727 | 728 | 729 | 730 | 731 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 732 | 1 733 | 734 | 735 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 736 | 1 737 | 738 | 739 | 740 | 741 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 742 | 1 743 | 744 | 745 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 746 | 1 747 | 748 | 749 | 750 | 751 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 752 | 1 753 | 754 | 755 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 756 | 1 757 | 758 | 759 | 760 | 761 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 762 | 1 763 | 764 | 765 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 766 | 1 767 | 768 | 769 | 770 | 771 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 772 | 1 773 | 774 | 775 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 776 | 1 777 | 778 | 779 | 780 | 781 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 782 | 1 783 | 784 | 785 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 786 | 1 787 | 788 | 789 | 790 | 791 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 792 | 1 793 | 794 | 795 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 796 | 1 797 | 798 | 799 | 800 | 801 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 802 | 1 803 | 804 | 805 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 806 | 1 807 | 808 | 809 | 810 | 811 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 812 | 1 813 | 814 | 815 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 816 | 1 817 | 818 | 819 | 820 | 821 | 1 822 | 823 | 824 | 1 825 | 826 | 827 | 828 | 829 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 830 | 1 831 | 832 | 833 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 834 | 1 835 | 836 | 837 | 838 | 839 | ..\ 840 | 1 841 | 842 | 843 | ..\ 844 | 1 845 | 846 | 847 | 848 | 849 | 1 850 | 851 | 852 | 1 853 | 854 | 855 | 1 856 | 857 | 858 | 859 | 860 | ..\$(PROJECTNAME).launchscreen 861 | 64 862 | 863 | 864 | ..\$(PROJECTNAME).launchscreen 865 | 64 866 | 867 | 868 | 869 | 870 | 1 871 | 872 | 873 | 1 874 | 875 | 876 | 1 877 | 878 | 879 | 880 | 881 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 882 | 1 883 | 884 | 885 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 886 | 1 887 | 888 | 889 | 890 | 891 | ..\ 892 | 1 893 | 894 | 895 | ..\ 896 | 1 897 | 898 | 899 | ..\ 900 | 1 901 | 902 | 903 | 904 | 905 | Contents 906 | 1 907 | 908 | 909 | Contents 910 | 1 911 | 912 | 913 | Contents 914 | 1 915 | 916 | 917 | 918 | 919 | Contents\Resources 920 | 1 921 | 922 | 923 | Contents\Resources 924 | 1 925 | 926 | 927 | Contents\Resources 928 | 1 929 | 930 | 931 | 932 | 933 | library\lib\armeabi-v7a 934 | 1 935 | 936 | 937 | library\lib\arm64-v8a 938 | 1 939 | 940 | 941 | 1 942 | 943 | 944 | 1 945 | 946 | 947 | 1 948 | 949 | 950 | 1 951 | 952 | 953 | Contents\MacOS 954 | 1 955 | 956 | 957 | Contents\MacOS 958 | 1 959 | 960 | 961 | Contents\MacOS 962 | 1 963 | 964 | 965 | 0 966 | 967 | 968 | 969 | 970 | library\lib\armeabi-v7a 971 | 1 972 | 973 | 974 | 975 | 976 | 1 977 | 978 | 979 | 1 980 | 981 | 982 | 983 | 984 | Assets 985 | 1 986 | 987 | 988 | Assets 989 | 1 990 | 991 | 992 | 993 | 994 | Assets 995 | 1 996 | 997 | 998 | Assets 999 | 1 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | False 1016 | False 1017 | False 1018 | False 1019 | False 1020 | False 1021 | True 1022 | False 1023 | 1024 | 1025 | 12 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | -------------------------------------------------------------------------------- /Test/Excel4DelphiTest.Converters.pas: -------------------------------------------------------------------------------- 1 | unit Excel4DelphiTest.Converters; 2 | 3 | interface 4 | 5 | uses DUnitX.TestFramework; 6 | 7 | type 8 | [TestFixture] 9 | TTestConvertrsObject = class 10 | public 11 | [Test] 12 | [TestCase('String to TDate 1', '12.10.2005')] 13 | [TestCase('String to TDate 2', '12-10-2005')] 14 | [TestCase('String to TDate 3', '12/10/2005')] 15 | [TestCase('String to TDate 4', '38637')] 16 | [TestCase('String to TDate 5', '20051012')] 17 | procedure TestConvertStringToDate(value: string); 18 | 19 | [Test] 20 | [TestCase('String to TDateTime 1', '12.10.2005 22:55:16')] 21 | [TestCase('String to TDateTime 2', '12-10-2005 22:55:16')] 22 | [TestCase('String to TDateTime 3', '12/10/2005 22:55:16')] 23 | //[TestCase('String to TDate 4', '38637,9550462963')] 24 | [TestCase('String to TDateTime 5', '38637.9550462963')] 25 | [TestCase('String to TDateTime 6', '2005-10-12T22:55:16')] 26 | procedure TestConvertStringToDateTime(value: string); 27 | end; 28 | 29 | implementation 30 | 31 | uses System.Variants, System.SysUtils, Soap.XSBuiltIns 32 | , Excel4Delphi 33 | , Excel4Delphi.Common 34 | ; 35 | 36 | { TTestConvertrsObject } 37 | 38 | procedure TTestConvertrsObject.TestConvertStringToDate(value: string); 39 | var dt, dt2: TDateTime; 40 | begin 41 | dt := 0; 42 | dt2 := EncodeDate(2005, 10, 12); 43 | Assert.AreEqual(ZETryParseDateTime(value, dt), true, 'String to TDate: bool'); 44 | Assert.AreEqual(dt, dt2, 'String to TDate'); 45 | end; 46 | 47 | procedure TTestConvertrsObject.TestConvertStringToDateTime(value: string); 48 | var dt, dt2: TDateTime; 49 | begin 50 | dt := 0; 51 | dt2 := EncodeDate(2005, 10, 12) + EncodeTime(22, 55, 16, 0); 52 | Assert.AreEqual(ZETryParseDateTime(value, dt), true, 'String to TDateTime: bool'); 53 | Assert.AreEqual(dt, dt2, 'String to TDateTime'); 54 | end; 55 | 56 | initialization 57 | TDUnitX.RegisterTestFixture(TTestConvertrsObject); 58 | 59 | end. 60 | -------------------------------------------------------------------------------- /Test/Excel4DelphiTest.Formula.pas: -------------------------------------------------------------------------------- 1 | unit Excel4DelphiTest.Formula; 2 | 3 | interface 4 | 5 | uses DUnitX.TestFramework; 6 | 7 | type 8 | [TestFixture] 9 | TTestFormulaObject = class 10 | public 11 | [Test] 12 | [TestCase('GetColAddres 1', '222')] 13 | procedure TestGetColAddres(value: integer); 14 | 15 | [Test] 16 | [TestCase('GetColIndex 1', 'HO')] 17 | procedure TestGetColIndex(value: string); 18 | 19 | [Test] 20 | [TestCase('GetCellCoords 1', 'B1')] 21 | procedure TestGetCellCoords(value: string); 22 | 23 | [Test] 24 | [TestCase('CellRange 1', 'B1:C2')] 25 | procedure TestCellRange(value: string); 26 | end; 27 | 28 | implementation 29 | 30 | uses System.Variants, System.SysUtils, Soap.XSBuiltIns 31 | , Excel4Delphi 32 | , Excel4Delphi.Formula 33 | ; 34 | 35 | { TTestFormulaObject } 36 | 37 | procedure TTestFormulaObject.TestCellRange(value: string); 38 | var left, top, right, bottom: integer; 39 | begin 40 | TZEFormula.GetCellRange(value, left, top, right, bottom); 41 | Assert.AreEqual(left, 1); 42 | Assert.AreEqual(top, 0); 43 | Assert.AreEqual(right, 2); 44 | Assert.AreEqual(bottom, 1); 45 | end; 46 | 47 | procedure TTestFormulaObject.TestGetCellCoords(value: string); 48 | var left, top: integer; 49 | begin 50 | TZEFormula.GetCellCoords(value, left, top); 51 | Assert.AreEqual(left, 1); 52 | Assert.AreEqual(top, 0); 53 | end; 54 | 55 | procedure TTestFormulaObject.TestGetColAddres(value: integer); 56 | var res: string; 57 | begin 58 | res := TZEFormula.GetColAddres(value); 59 | Assert.AreEqual(res, 'HO'); 60 | end; 61 | 62 | procedure TTestFormulaObject.TestGetColIndex(value: string); 63 | var res: Integer; 64 | begin 65 | res := TZEFormula.GetColIndex(value); 66 | Assert.AreEqual(res, 222); 67 | end; 68 | 69 | initialization 70 | TDUnitX.RegisterTestFixture(TTestFormulaObject); 71 | 72 | end. 73 | -------------------------------------------------------------------------------- /Test/Excel4DelphiTest.pas: -------------------------------------------------------------------------------- 1 | unit Excel4DelphiTest; 2 | 3 | interface 4 | 5 | uses DUnitX.TestFramework 6 | , Excel4Delphi 7 | , Excel4Delphi.Xml 8 | , Excel4Delphi.Stream 9 | ; 10 | 11 | const FILE_1 = '../../Examples/Test1.xlsx'; 12 | 13 | type 14 | [TestFixture] 15 | TTestObject = class 16 | public 17 | [Test] 18 | [TestCase('TestDropColumnAndRows 1', FILE_1)] 19 | procedure TestDropColumnAndRows(fileName: string); 20 | end; 21 | 22 | implementation 23 | 24 | { TTestObject } 25 | 26 | procedure TTestObject.TestDropColumnAndRows(fileName: string); 27 | var book: TZWorkBook; 28 | begin 29 | book := TZWorkBook.Create(nil); 30 | try 31 | book.LoadFromFile(fileName); 32 | 33 | Assert.AreEqual(book.Sheets[0].MergeCells.Count, 6, 'Merged count'); 34 | 35 | book.Sheets[0].DeleteColumns(9, 1); 36 | Assert.AreEqual(book.Sheets[0].MergeCells.Count, 5, 'Merged count'); 37 | 38 | book.Sheets[0].DeleteColumns(6, 1); 39 | Assert.AreEqual(book.Sheets[0].MergeCells.Count, 5, 'Merged count'); 40 | 41 | book.Sheets[0].DeleteRows(4, 1); 42 | Assert.AreEqual(book.Sheets[0].MergeCells.Count, 4, 'Merged count'); 43 | 44 | book.SaveToFile('test_del_rows.xlsx'); 45 | finally 46 | book.Free(); 47 | end; 48 | end; 49 | 50 | initialization 51 | TDUnitX.RegisterTestFixture(TTestObject); 52 | 53 | end. 54 | --------------------------------------------------------------------------------