HotXLS có thể viết lại một worksheet bên trong một package XLSX hiện có mà không cần phân tích hay nén lại phần còn lại của file. TXLSDirectWriter.BeginPatch mở một package nguồn, sao chép mọi mục ngoại trừ sheet mục tiêu sang nguyên vẹn với byte đã nén của chúng, và cho phép bạn viết lại đúng sheet đó qua các lệnh gọi AddSheet, AddRow và Write* thông thường. Biểu đồ, cache pivot, theme, style và chuỗi dùng chung hoàn toàn không bị giải nén
Quy trình mà tính năng này giải quyết xuất hiện trong báo cáo và làm mới dữ liệu. Một workbook đến từ đội ngũ kinh doanh mang theo bảng pivot, slicer, định dạng có điều kiện và cả một thập kỷ định dạng tích lũy. Mỗi đêm một sheet dữ liệu phải được thay bằng số liệu mới. Tải rồi lưu lại toàn bộ workbook tốn hàng phút cho mỗi file và, quan trọng hơn, gây rủi ro về độ trung thực đối với các tính năng mà bộ tải phải dựng lại. Việc vá tránh được cả hai vấn đề bằng cách không chạm vào những gì nó không cần chạm
Vì sao sao chép byte đã nén lại là phần thú vị?
Một mục zip được sao chép ở cấp đã nén chỉ tốn một lần sao chép luồng. Cùng mục đó đi qua đường ghi bình thường tốn một lần giải nén (inflate) khi vào và một lần nén (deflate) khi ra, và deflate là nửa đắt đỏ hơn. Trên một workbook có cache pivot lớn và vài chục hình ảnh nhúng, sự khác biệt đó là khoảng cách giữa một bản vá hoàn tất trong thời gian đủ để ghi sheet mới và một bản vá tốn phần lớn thời gian nén lại những byte mà nó chưa từng xem qua
HotXLS dùng CopyCompressedFrom cho việc này, hàm ghi thẳng byte đã nén của mục nguồn vào kho lưu trữ đích. Khi một mục không thể sao chép theo cách đó, vì nó dùng phương thức nén khác hoặc mã hóa yếu, bộ ghi quay về sao chép luồng đã giải nén thay vì thất bại. Các mục đánh dấu thư mục bị bỏ qua, vì bộ ghi tự tạo ra thư mục của riêng nó
Thay thế tại chỗ, hoặc ghi ra file mới
Hai overload bao phủ hai dạng mà tác vụ này có thể có. Dạng tại chỗ dàn dựng kết quả trong một file tạm bên cạnh bản gốc, đóng handle nguồn, rồi xóa và đổi tên, nên một sự cố crash giữa chừng khi ghi vẫn giữ nguyên bản gốc. Dạng đích tường minh giữ nguồn không bị chạm và có thể hoặc thay thế một sheet hoặc thêm một sheet mới:
var
W: TXLSDirectWriter;
begin
W := TXLSDirectWriter.Create;
try
W.BeginPatch('monthly-dashboard.xlsx', 'Data'); // tại chỗ
W.AddSheet('Data');
W.AddRow(1);
W.WriteString(1, 'Region');
W.WriteString(2, 'Revenue');
W.AddRow(2);
W.WriteString(1, 'North');
W.WriteNumber(2, 184320.55);
W.AddRow(3);
W.WriteFormula(1, '=SUM(B2:B2)');
W.Close;
finally
W.Free;
end;
end;
Biến thể chèn nhận một đường dẫn nguồn và một đường dẫn đích cộng thêm InsertSheet:
// Nguồn không bị chạm; đích nhận thêm một worksheet tên là Extra
W.BeginPatch('template.xlsx', 'output.xlsx', 'Extra', True);
W.AddSheet('Extra');
W.AddRow(1);
W.WriteString(1, 'appended by the nightly job');
W.Close;
Chèn thêm là phần đòi hỏi thao tác sổ sách thực sự phức tạp. Bộ ghi phân tích sổ đăng ký sheet trong xl/workbook.xml và bản đồ quan hệ ràng buộc mỗi sheet với phần của nó, rồi chọn số phần tự do tiếp theo, định danh sheet và định danh quan hệ. Loại quan hệ theo đúng quy ước của package nguồn, nên vá một workbook ISO 29500 strict phát ra loại quan hệ strict và vá một workbook chuyển tiếp phát ra loại quan hệ chuyển tiếp
Những gì bản vá cố tình bỏ đi và ràng buộc
Chuỗi tính toán (calculation chain) bị loại bỏ trong cả hai chế độ. Ở chế độ thay thế, các mục của nó mô tả các ô trong một sheet không còn tồn tại ở dạng đó nữa; ở chế độ chèn, việc dịch chỉ số sheet làm nó vô hiệu hoàn toàn. Excel dựng lại chuỗi này trong lần tính toán lại tiếp theo, nên việc loại bỏ nó là đúng đắn chứ không phải mất mát dữ liệu. Phần này bị loại khỏi bản sao, và mục quan hệ cùng ghi đè loại nội dung của nó bị gỡ bỏ một cách chính xác
Hai ngữ nghĩa tạo file thay đổi bên trong một bản vá, và cả hai đều xuất phát từ cùng một nguyên tắc: bản vá không được làm xáo trộn những phần nó không viết lại. Chuỗi được ghi trực tiếp vào trong sheet thay vì thêm vào bảng chuỗi dùng chung, vì bảng nguồn đi qua không bị chạm. Và StyleIndex tham chiếu đến các mục trong cellXfs của package nguồn, không phải một bảng style mà bộ ghi tự xây dựng. Điều đó nghĩa là bạn có thể tham chiếu các định dạng mà workbook gốc đã định nghĩa sẵn, thường chính xác là điều mà một lần làm mới dữ liệu muốn, nhưng nó cũng có nghĩa là bạn phải biết chỉ số nào mang định dạng nào
// Bên trong một bản vá, StyleIndex đánh chỉ mục vào cellXfs của
// package NGUỒN. Một ngày tháng cần chỉ mục tường minh ánh xạ
// đến định dạng ngày ở đó:
W.WriteDateTime(3, EncodeDate(2026, 8, 22), DateStyleIndexFromTemplate);
// Overload WriteDateTime không kèm style bị từ chối ở chế độ vá,
// vì nó giả định bảng style riêng của bộ ghi, thứ mà một bản vá
// không bao giờ tạo ra
Sáu điểm vào để tạo file bị chặn: thêm bảng, biểu đồ, hình ảnh, bình luận, tên đã định nghĩa và style ô đều phát sinh ngoại lệ ở chế độ vá, kèm một lưới an toàn thứ hai tại thời điểm đóng, nơi thất bại nếu bất kỳ bộ đếm nào trong số đó khác không. Mỗi tính năng đó đòi hỏi chỉnh sửa các phần mà bản vá sao chép nguyên văn, và một package sửa nửa chừng còn tệ hơn một thao tác bị từ chối. Chính xác một sheet có thể được vá cho mỗi thao tác
Khi nào vá và khi nào tải
Vá là công cụ đúng khi workbook lớn, thay đổi giới hạn trong một sheet, và phần còn lại của file phải sống sót nguyên vẹn từng bit. Đó là công cụ sai khi thay đổi trải rộng qua nhiều sheet, khi cần định dạng mới hoặc đối tượng mới, hoặc khi file đủ nhỏ để một lần tải và lưu bình thường không tốn gì cả. Với việc tạo hàng loạt từ đầu, đường dẫn streaming được mô tả trong bộ ghi trực tiếp dạng streaming vẫn là lựa chọn phù hợp hơn, và nó dùng chung API AddRow và Write*, nên chuyển đổi giữa hai cách này mang tính máy móc
Thao tác cấp sheet bên trong một workbook đã tải, khi bạn thực sự muốn dùng mô hình đối tượng đầy đủ, được đề cập trong nhân bản worksheet trong package XLSX. Và nếu lý do bạn cân nhắc dùng bản vá là vì xử lý toàn workbook đã trở nên chậm chạp, các số đo và hành vi bộ nhớ trong hiệu năng với workbook lớn đáng đọc trước khi chọn cách tiếp cận
Xác minh một bản vá thực sự làm đúng điều bạn nghĩ
Ba kiểm tra bắt được gần như mọi sai sót. Xác nhận rằng các phần bạn mong đợi tồn tại vẫn còn trong kho lưu trữ, rằng xl/calcChain.xml đã biến mất, và rằng mở lại file qua TXLSXWorkbook báo cáo đúng số sheet bạn mong đợi, không đổi đối với thay thế và tăng thêm một đối với chèn. Đọc lại sheet đã vá và so sánh vài giá trị và công thức khép lại vòng lặp kiểm tra
Một chi tiết triển khai từ quá trình phát triển tính năng này đáng được nhắc lại, vì nó có thể gây hại cho bất kỳ ai viết mã cấp zip tương tự. Tên phần worksheet được khớp theo tiền tố, và một lỗi lệch một đơn vị (off-by-one) trong độ dài tiền tố có nghĩa là vị từ (predicate) không bao giờ khớp, nên một phần mới được ghi va chạm với tên đã tồn tại và những trình đọc lấy mục cuối cùng có cùng tên sẽ âm thầm chọn nhầm sheet. Nếu một bản vá có vẻ hoán đổi nội dung của hai sheet, hãy xem xét việc khớp tên trước khi xem xét XML
Vá tại chỗ, ghi streaming và mô hình đối tượng workbook đầy đủ đều nằm trong cùng thư viện cho Delphi và C++Builder; danh sách tính năng có trên trang thành phần bảng tính HotXLS Delphi