HotXLS läser och skriver Excel Binary Workbook-filer (XLSB) från Delphi via samma TXLSXWorkbook-fasad som för XLSX: Open detekterar en binär arbetsbok ur paketinnehållet, och SaveAs eller SaveAsChecked med xlsxExcelBinaryWorkbook skriver en. Backend:en täcker en validerad delmängd och avvisar allt den inte kan representera innan den vidrör destinationen
Den sista klausulen är delen värd att läsa långsamt. XLSB ser ut som en enkel variant av XLSX, och i pakettermer är det den. Problemen bor i detaljerna de två formaten kodar olika, och i vad ett bibliotek tyst antar när det broar det ena in i det andra. Den mest lärorika buggen i den här backend:en var inte en felformad post alls. Det var ett standardtypsnitt som försvann, och en datumkolumn som blev #### i Excel fast värdet, formatkoden och kolumnbredden alla var korrekta
Vad är en XLSB-fil, och hur skiljer den sig från XLSX?
En XLSB-fil är ett OPC-paket med exakt den delstruktur en XLSX-arbetsbok har, men arbetsboks-, kalkylblads-, stil- och delade-sträng-delarna lagrar binära poster i stället för XML. Formatet är specificerat i [MS-XLSB], och postkodningen kallas ofta BIFF12. Du får fortfarande [Content_Types].xml, relationsdelar och en ZIP-container; det som ändras är att xl/workbook.bin ersätter xl/workbook.xml, xl/worksheets/sheet1.bin ersätter kalkylblads-XML:n, och så vidare
Varje BIFF12-post börjar med ett kompakt huvud med variabel längd. Posttypen tar en eller två bytes, sju bitar per byte med högsta biten som fortsättningsflagga, så en posttyp ryms i 14 bitar. Nyttlaststorleken följer i en till fyra bytes med samma sjubitarschema. Strängar är ett 32-bitars teckenantal följt av UTF-16-kodenheter. Jämfört med BIFF8 är det en mycket renare layout: ingen 8224-bytes-CONTINUE-splittring, inga komprimerad-mot-bred-sträng-flaggor mitt i posten. Jämfört med XLSX hoppar den över XML-tokenisering helt, vilket är varför stora XLSB-filer tenderar att vara mindre på disk och snabbare för Excel att öppna
En paketdetalj snubblar detekteringskod. Excel registrerar XLSB-arbetsboksdelen med content type application/vnd.ms-excel.sheet.binary.macroEnabled.main, även för arbetsböcker som inte innehåller några makron. HotXLS kontrollerar den registreringen i [Content_Types].xml först och faller bara tillbaka på .bin-delextensionen när content type saknas, och endera vägen måste fortfarande klara den strikta postvalidatorn. De allmänna reglerna om delnamn, relationer och content types är samma som täcks i varför Excel reparerar en giltig XLSX och OPC-paketreglerna bakom det
När ska du välja XLSB före XLSX?
Välj XLSB när ett nedströmssystem kräver det eller när du utväxlar stora värdestunga arbetsböcker med Excel-användare som bryr sig om öppningstid; annars förblir XLSX det säkrare standardvalet. XLSX är en ISO-standard (ISO/IEC 29500) med brett verktygsstöd, den är inspekterbar med ett ZIP-verktyg och en textredigerare, och varje kalkylarksprodukt läser den. XLSB är ett Microsoft-format med en publicerad specifikation men ett smalare ekosystem
I praktiken kommer förfrågningarna från två håll. Vissa rapporteringspipelines och arkiv standardiserade på .xlsb för år sedan och avvisar allt annat. Andra team genererar arbetsböcker med hundratusentals numeriska celler och fann att användare öppnar den binära versionen märkbart snabbare. Båda är legitima skäl. "Det låter mer effektivt" är det inte, eftersom HotXLS binära backend mellanlagrar hela paketet i minnet, så den är inte verktyget för serverexporter med begränsat minne. För dem är den strömmande XLSX-skrivaren rätt väg
Öppna och spara XLSB med TXLSXWorkbook
TXLSXWorkbook.Open behöver inget formattips: samma anrop laddar XLSX, XLSM eller XLSB, och efter en lyckad binär laddning rapporterar TXLSXWorkbook.SourceFormat xlsxExcelBinaryWorkbook. Skrivning är explicit. SaveAs(FileName) utan format producerar alltid en Open XML-arbetsbok, även när filnamnet slutar på .xlsb, så binär utdata namnger alltid formatet
uses
SysUtils, lxHandleX;
procedure ConvertToXlsb(const Source, Target: string);
var
Book: TXLSXWorkbook;
begin
Book := TXLSXWorkbook.Create;
try
// Open detekterar XLSX, XLSM eller XLSB ur paketet självt
if Book.Open(Source) <> 1 then
raise Exception.Create('Input is unsupported or invalid');
// Enbart extensionen väljer aldrig binär utdata
if Book.SaveAsChecked(Target, xlsxExcelBinaryWorkbook) <> 1 then
raise Exception.Create('XLSB output is unsupported or failed');
finally
Book.Free;
end;
end;
Strömutdata går via SaveAs(Stream, xlsxExcelBinaryWorkbook) eller strömöverladdningen av SaveAsChecked. Internt dirigerar båda till de privata metoderna SaveAsXlsbStream och SaveAsXlsbFile; du anropar dem aldrig direkt. Filutdata mellanlagras i en syskon-temporärfil och committas med en enda slutlig ersättning. En strömdestination måste vara läsbar och sökbar, eftersom skrivaren snapshot:ar dess bytes, storlek och position och återställer dem om den slutliga kopieringen misslyckas. TXLSXWorkbook.LastSaveUsedStreaming rapporterar False efter en binär sparning, vilket är korrekt: hela paketet finns i minnet innan en enda byte når din destination
Varför en validerad delmängd i stället för full trohet?
HotXLS underhåller ingen andra objektmodell för XLSB. Vid öppning konverterar XlsbToOpenXml det binära paketet till ett Open XML-paket i minnet och den vanliga XML-parsern laddar det; vid sparning bygger XML-skrivaren ett paket och OpenXmlToXlsb kodar det som binära poster. Varje funktion måste därför överleva två översättningar, och en funktion bron inte kan översätta exakt avvisas i stället för att approximeras
Den stödda uppsättningen i HotXLS 2.384.113 är bred nog för de flesta dataarbetsböcker: typade värden, delade och inline-strängar, vanliga typsnitt, fyllnader, kanter och talformat, radhöjder och kolumnbredder, vanliga cellformler med cachade resultat, definierade namn, sammanslagna celler, hyperlänkar, frysta och delade rutor, AutoFilter-intervall med enkla egna kriterier, och vanliga kalkylbladstabeller. Utanför den sitter delade och array-formler, future- och användardefinierade funktioner, referenser till externa arbetsböcker, diagram och ritningar, PivotTables och slicers, VBA, villkorsstyrd formatering, datavalidering och icke-standardberäkningsinställningar som manuell beräkning eller iteration
Avvisning är obligatorisk, inte rådgivande. TXLSXWorkbook.GetConversionReport(xlsConversionExcelBinaryWorkbook) listar ostödda funktioner innan du sparar, och de posterna fallerar sparningen även med AAllowLossy = True eller en okontrollerad SaveAs. Det är medvetet. Att tyst tappa en PivotTable ur en binär kopia är den sortens förlust ingen lägger märke till förrän arbetsboken ligger framför en kund
uses
Classes, lxHandleX, lxDiagnostics;
function CanSaveAsXlsb(Book: TXLSXWorkbook; Log: TStrings): Boolean;
var
Report: TXLSConversionReport;
I: Integer;
begin
Report := Book.GetConversionReport(xlsConversionExcelBinaryWorkbook);
try
Result := True;
for I := 0 to Report.Count - 1 do
if Report[I].Fidelity = xlsConversionUnsupported then
begin
Result := False;
Log.Add(Report[I].SheetName + ' ' + Report[I].Location + ': ' +
Report[I].Feature + ' - ' + Report[I].Message);
end;
finally
Report.Free; // anroparen äger rapporten
end;
end;
Rapporten täcker den levande modellen. Slutlig paketvalidering är fortfarande den sista grinden för saker modellen aldrig ser, som felformade poster eller obekanta attribut i källfilen, så en ren rapport följt av en fallerad sparning är möjlig och sparningsresultatet är det du agerar på
Varför försvann standardtypsnittet och 0.00-formatet?
Standardtypsnittet och de inbyggda talformaten försvann eftersom XML-stil-läsaren gjorde två antaganden som håller för filer HotXLS skriver självt men inte för arbetsböcker Excel skriver. Bron bevarade båda resurserna perfekt; förlusten skedde ett lager upp, i den publika Open-vägen. Det gapet är huvudläxan från den här backend:en: en korrekt formatbro garanterar inte en trogen publik rundtur
Det första antagandet gällde fonts[0]. När HotXLS sparar XLSX skriver den ett implicit standardtypsnitt i lucka noll, och dess XML-läsare hoppar över den luckan så den användarriktade Fonts-samlingen börjar på index noll. En Excel-författad XLSB bär sitt eget explicita standardval i den luckan, och att hoppa över den kastade bort det valet. Det andra antagandet gällde talformat. Läsaren mappade bara egna numFmtId-värden (164 och uppåt) in i NumberFormats; inbyggda id:n stannade som noll. En formaterad tom cell som bar inbyggt format 2, vilket är 0.00, kom tillbaka som General
Fixen bor helt i den binära importvägen. Efter att hela paketet klarat preflighten sätter XLSB-öppningen ett privat stilläge för den synkrona XML-parsningen bara. I det läget laddar läsaren varje typsnitt inklusive lucka noll och skiftar varje fontId med ett, konverterar varje stött inbyggt id till en explicit formatkod i modellen, och använder fortfarande det ursprungliga numFmtId för datumdetektering, så ett inbyggt datumformat behåller sin datumesemantik. Ett finally-block rensar alltid läget, och en senare vanlig XLSX- eller ODS-Open rensar det bevarade standardtypsnittstillståndet också
Hur påverkar fonts[0] Excel:s kolumnbredder?
Excel beräknar kolumnbredder ur arbetsbokens standardtypsnitt i fonts[0], inte ur de typsnitt som applicerats på cellerna i den kolumnen. Kolumnens width lagras i teckenenheter av standardtypsnittets maximala sifferbredd, så att ändra fonts[0] ändrar pixelbredden på varje kolumn, inklusive kolumner vars celler alla använder ett annat typsnitt
Det producerade det mest förvirrande symptomet under hela utredningen. Den om-sparade arbetsboken hade identiska cellvärden, identiska formatkoder och identiska width-attribut, celltypsnittet och Normal-stilen pekade båda på det bevarade typsnittet, och Excel renderade ändå en datumkolumn som ####. Det skrivna fonts[0] hade återgått till Calibri 11, den maximala sifferbredden krympte, och datumen fick inte längre plats. HotXLS behåller nu källans standardtypsnitt och skriver tillbaka det som fonts[0], med fall tillbaka till Calibri 11 bara för arbetsböcker som aldrig haft en binär källa. Hela breddaritmetiken finns i Excel-kolumnbredd och max digit width (MDW) i Delphi
Språkberoende inbyggda format avvisas, inte gissas
Ett inbyggt talformat-id utan explicit formatkod accepteras bara när dess betydelse är fast; språkberoende id:n avvisas under paketpreflighten. HotXLS mappar id 0 till 22, 37 till 40 och 45 till 49 till kända koder som 0.00, 0%, mm:ss och @. De återstående id:na under 164 tillhör format vars rendering beror på Excel-installationens regionala inställningar, och importen vägrar dem med meddelandet "A locale-dependent number format requires an explicit format code"
Att hitta på en kod för de id:na vore värre än att fallera. Ett gissat östasiatiskt datummönster ser rimligt ut, går runt utan fel och visar fel sak för hälften av dina användare. Tidpunkten spelar också roll: kontrollen körs i hel-paket-preflighten, innan den befintliga arbetsboken rensas, så en avvisad fil lämnar den tidigare laddade modellen, filnamnet och källformatet orörda. Artikeln om Excel-datums serial och numFmt täcker hur inbyggda datum-id samspelar med 1900- och 1904-datumsystemen
procedure LoadBinaryWorkbook(Book: TXLSXWorkbook; const FileName: string);
var
I: Integer;
begin
// Binär indata kräver ivrig full laddning; selektiva lägen avvisar i förväg
Book.MetadataOnly := False;
Book.SelectedSheets.Clear;
if Book.Open(FileName) <> 1 then
begin
for I := 0 to Book.Diagnostics.Count - 1 do
Writeln(Book.Diagnostics[I].Message);
Exit; // den tidigare laddade arbetsboken är fortfarande intakt
end;
// Formelutdata behöver en cache om inte sparningen räknar om
Book.RecalcBeforeSave := xrmAlways;
end;
Praktiska regler för XLSB i produktionskod
Den binära backend:en är säker att lita på när du behandlar dess avvisanden som data snarare än som fel att undertrycka. Några regler följer av beteendet ovan
- Namnge formatet vid varje binär sparning; enbart extensionen
.xlsbproducerar fortfarande XLSX - Kör
GetConversionReport(xlsConversionExcelBinaryWorkbook)före sparning av användarredigerade arbetsböcker och för fram de ostödda funktionerna för användaren - Låt
MetadataOnlyvara av ochSelectedSheetstom för binär indata, eftersom lazy loading skulle kräva att behålla ett konverterat arkiv - Ge formler ett cachat resultat eller räkna om före sparning, eftersom en saknad cache avvisas under
xrmManualoch under en renxrmIfDirty - Budgetera minne för hela det konverterade paketet plus den binära utdatan; använd strömmande XLSX när minnet måste hållas avgränsat
När du testar, jämför mot Excel genom det publika API:et snarare än på bronivå. Standardtypsnitts- och 0.00-regressionerna klarade båda bro-testerna, och båda dök upp omedelbart i en Excel-författad arbetsbok som öppnats och sparats om genom Open och SaveAsChecked
FAQ
Detekterar HotXLS XLSB-filer automatiskt?
Ja. TXLSXWorkbook.Open inspekterar den content type som registrerats för arbetsboksdelen och validerar de binära posterna, så samma anrop laddar XLSX och XLSB, och SourceFormat rapporterar vilken som lästes
Varför skriver SaveAs med ett .xlsb-filnamn fortfarande XLSX?
HotXLS härleder aldrig utdataformatet ur extensionen. Skicka xlsxExcelBinaryWorkbook till SaveAs eller SaveAsChecked för att skriva en binär arbetsbok
Vad händer när en arbetsbok använder funktioner utanför XLSB-delmängden?
Sparningen fallerar innan destinationen ändras, även med förlustgivande sparning tillåten. GetConversionReport listar de blockrande funktionerna i förväg, och Diagnostics förklarar felet efteråt
XLSB-stöd, konverteringsrapporten och resten av arbetsboks-API:et medföljer HotXLS, den inbyggda Delphi- och C++Builder-spreadsheet-komponenten