Artykuł techniczny

Ładowanie XLSX tylko metadanych i selektywne z HotXLS

HotXLS potrafi otworzyć skoroszyt XLSX i nie sparsować ani jednej komórki arkusza. TXLSXWorkbook.MetadataOnly czyta właściwości skoroszytu, zdefiniowane nazwy, nazwy arkuszy i stany widoczności, style, motyw, połączenia i łącza zewnętrzne, a potem zatrzymuje się przed XML-em komórek. Dla skanera, który musi wiedzieć, co jest w katalogu skoroszytów, to jest różnica między minutami a sekundami

Trzy powiązane przełączniki dopełniają obrazu: SelectedSheets parsuje komórki dla nazwanego podzbioru, LoadSheet materializuje pominięty arkusz później z oryginalnego archiwum, a PreserveRawParts kopiuje skompresowane bajty niezmienionych części prosto przy zapisie. Użyte razem zmieniają „otwórz skoroszyt" z jednej operacji wszystko-albo-nic w coś, co możesz ograniczyć

Co można się dowiedzieć bez parsowania ani jednej komórki?

Więcej, niż wymaga większość zadań wykrywania. Przy MetadataOnly ustawionym przed Open skoroszyt wraca niosąc swoje nazwy arkuszy i stany widoczności, zdefiniowane nazwy, właściwości dokumentu, style i motyw, łącza zewnętrzne i połączenia. Arkusze są obecne jako obiekty z zerem komórek

To jest dokładnie informacja, na której działa katalog, audyt albo decyzja trasująca. Które skoroszyty definiują nazwę TaxRate? Które mają ukryte arkusze? Które linkują do serwera, który został wycofany? Odpowiadanie na to pełnym ładowaniem każdego pliku to właśnie tak nocne zadanie staje się zadaniem na całą noc

var
  Workbook: TXLSXWorkbook;
  I: Integer;
begin
  Workbook := TXLSXWorkbook.Create(nil);
  try
    Workbook.MetadataOnly := True;      // set before Open
    Workbook.Open(FileName);
    for I := 1 to Workbook.Sheets.Count do      // Sheets[] is 1-based
      if not Workbook.Sheets[I].Visible then
        Report.Add(FileName + ': hidden sheet ' +
          Workbook.Sheets[I].Name);
  finally
    Workbook.Free;
  end;
end;

Ładowanie dwóch arkuszy z czterdziestu

SelectedSheets to TStringList nazw arkuszy. Gdy nie jest pusta, Open parsuje XML komórek tylko dla arkuszy, które wymienia; każdy inny arkusz zachowuje poprawną nazwę i stan widoczności i nie trzyma komórek. Pusta lista oznacza poprzednie zachowanie, czyli załadowanie wszystkiego

Interakcja z MetadataOnly warto wypowiedzieć wprost, ponieważ odwrotne ustawienie produkuje zagadkowo pusty skoroszyt: MetadataOnly = True przesłania selekcję i pomija wszystkie arkusze. Używaj jednego albo drugiego. Wykrywanie używa tylko metadanych; praca docelowa używa selekcji

Workbook.SelectedSheets.Add('Summary');
Workbook.SelectedSheets.Add('Q3 Detail');
Workbook.Open('consolidated-2026.xlsx');
// Later, when the user opens a tab you skipped.
// LoadSheet takes the 0-based position and needs the source file,
// so it does not work on a workbook opened from a stream
if Workbook.LoadSheet(ZeroBasedPosition) then
  Grid.Refresh;

LoadSheet(Index) materializuje pominięty arkusz na żądanie z oryginalnego archiwum, co właśnie czyni ten wzorzec użytecznym w aplikacji interaktywnej zamiast tylko w partii. Otwórz z arkuszem, na który patrzy użytkownik, załaduj resztę, gdy kliknie. Archiwum zostaje otwarte właśnie z tego powodu, więc trzymaj skoroszyt żywy tak długo, jak użytkownik może poprosić o kolejny arkusz

Dlaczego podróż w obie strony zmienia części, których nigdy nie tknąłeś?

Ponieważ naiwny zapis regeneruje wszystko. Dekompresuj motyw, zbuduj model obiektów, serializuj go z powrotem, skompresuj ponownie — i teraz bajty się różnią, mimo że nic w motywie się nie zmieniło. Dla projektów VBA i pamięci podręcznych pivot jest to gorsze niż marnotrawne, ponieważ te części niosą strukturę, której model obiektów w pełni nie reprezentuje

PreserveRawParts odpowiada na to, kopiując skompresowaną reprezentację niezmienionych części bezpośrednio z archiwum źródłowego podczas SaveAs. Motyw, projekt VBA, tabele pivot i pamięci podręczne pivot przechodzą jako bajty, gdy nie zostały zmodyfikowane. Bez dekompresji, bez rekompresji, bez ryzyka zgubienia czegoś w podróży serializacji

Kosztem jest ograniczenie, które już miałeś: archiwum źródłowe musi być wciąż dostępne w czasie zapisu. Jeśli Twój przepływ wczytuje plik do pamięci, zamyka go i zapisuje godzinę później, ścieżka surowego kopiowania nie ma z czego kopiować. Utrzymuj źródło osiągalne przez czas życia skoroszytu, co jest tym samym wymogiem, jaki imposes LoadSheet

Potok wykrywania, który otwiera ponownie celowo

Wzorzec działający w produkcji ma dwa przebiegi i żadnej sprytu. Przebieg pierwszy otwiera tylko metadane i decyduje. Przebieg drugi otwiera ponownie pliki, na których zależy, z selekcją arkuszy i wykonuje pracę. Ponowne otwarcie wydaje się marnotrawne, dopóki nie policzysz, czego unikał przebieg pierwszy: drugie otwarcie to jedyne, które parsuje komórki, i parsuje tylko arkusze wyselekcjonowane w przebiegu pierwszym

// Pass 1: discovery
Workbook.MetadataOnly := True;
Workbook.Open(FileName);
Wanted := SheetsMatching(Workbook, 'Invoice');
Workbook.Free;

// Pass 2: targeted load
Workbook := TXLSXWorkbook.Create(nil);
Workbook.SelectedSheets.AddStrings(Wanted);
Workbook.Open(FileName);

Nie próbuj promować skoroszytu tylko metadanych w miejscu przez czyszczenie flagi po Open. Flaga jest czytana podczas otwierania; wyczyszczenie jej po zmianie niczego nie zmienia w skoroszycie, którego XML komórek nigdy nie został odwiedzony

Gdzie to się mieści z innymi dźwigniami dużego pliku

Selektywne ładowanie redukuje to, co parsujesz. Nie redukuje tego, co kosztuje arkusz raz załadowany, i nie pomaga, gdy faktycznie potrzebujesz każdej komórki każdego arkusza. Dla tego przypadku właściwa praca leży po stronie pamięci, opisana w notatkach o pamięci komórek w blokach wierszy i nakładkach stylu interwałowego, oraz po stronie parsowania w równoległym parsowaniu XLSX i alokatorze pamięci. Gdy zadaniem jest czyste skanowanie bez edycji w ogóle, strumieniowy czytnik bezpośredni pomija model obiektów w całości i pobije każdą strategię ładowania, która go buduje

HotXLS otwiera pliki XLS i XLSX z natywnego kodu Delphi i C++Builder bez zależności od Excela, więc zadanie wykrywania po stronie serwera działa bez niczego zainstalowanego poza własnym plikiem wykonywalnym — zobacz stronę komponentu arkuszowego HotXLS, by poznać obsługiwane formaty i licencjonowanie