@visactor/vtable-plugins 1.22.8-alpha.13 → 1.22.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/excel-import/excel.d.ts +23 -0
- package/cjs/excel-import/excel.js +204 -0
- package/cjs/excel-import/excel.js.map +1 -0
- package/cjs/excel-import/index.d.ts +3 -0
- package/cjs/excel-import/index.js +39 -0
- package/cjs/excel-import/index.js.map +1 -0
- package/cjs/excel-import/types.d.ts +44 -0
- package/cjs/excel-import/types.js +6 -0
- package/cjs/excel-import/types.js.map +1 -0
- package/cjs/excel-import/vtable-sheet.d.ts +2 -0
- package/cjs/excel-import/vtable-sheet.js +31 -0
- package/cjs/excel-import/vtable-sheet.js.map +1 -0
- package/cjs/excel-import.d.ts +12 -22
- package/cjs/excel-import.js +107 -40
- package/cjs/excel-import.js.map +1 -1
- package/cjs/filter/filter-toolbar.d.ts +1 -0
- package/cjs/filter/filter-toolbar.js +5 -4
- package/cjs/filter/filter-toolbar.js.map +1 -1
- package/cjs/filter/index.js +1 -2
- package/cjs/filter/value-filter.js +1 -1
- package/cjs/filter/value-filter.js.map +1 -1
- package/cjs/master-detail-plugin/checkbox.js +1 -0
- package/cjs/master-detail-plugin/index.js +1 -1
- package/cjs/master-detail-plugin/subtable.js +1 -1
- package/cjs/master-detail-plugin/table-api-extensions.js +1 -1
- package/cjs/master-detail-plugin/types.js +1 -1
- package/cjs/table-export/excel/index.d.ts +4 -0
- package/cjs/table-export/excel/index.js +72 -36
- package/cjs/table-export/excel/index.js.map +1 -1
- package/cjs/table-export/index.d.ts +2 -2
- package/cjs/table-export/index.js +6 -1
- package/cjs/table-export/index.js.map +1 -1
- package/cjs/table-export.js +4 -1
- package/cjs/table-export.js.map +1 -1
- package/cjs/table-series-number.js +1 -0
- package/cjs/table-series-number.js.map +1 -1
- package/dist/vtable-plugins.js +591 -122
- package/dist/vtable-plugins.min.js +3 -3
- package/es/excel-import/excel.d.ts +23 -0
- package/es/excel-import/excel.js +190 -0
- package/es/excel-import/excel.js.map +1 -0
- package/es/excel-import/index.d.ts +3 -0
- package/es/excel-import/index.js +4 -0
- package/es/excel-import/index.js.map +1 -0
- package/es/excel-import/types.d.ts +44 -0
- package/es/excel-import/types.js +2 -0
- package/es/excel-import/types.js.map +1 -0
- package/es/excel-import/vtable-sheet.d.ts +2 -0
- package/es/excel-import/vtable-sheet.js +25 -0
- package/es/excel-import/vtable-sheet.js.map +1 -0
- package/es/excel-import.d.ts +12 -22
- package/es/excel-import.js +110 -40
- package/es/excel-import.js.map +1 -1
- package/es/filter/filter-toolbar.d.ts +1 -0
- package/es/filter/filter-toolbar.js +6 -4
- package/es/filter/filter-toolbar.js.map +1 -1
- package/es/filter/index.js +1 -2
- package/es/filter/value-filter.js +1 -1
- package/es/filter/value-filter.js.map +1 -1
- package/es/master-detail-plugin/checkbox.js +2 -1
- package/es/master-detail-plugin/index.js +1 -1
- package/es/master-detail-plugin/subtable.js +1 -1
- package/es/master-detail-plugin/table-api-extensions.js +1 -1
- package/es/master-detail-plugin/types.js +1 -1
- package/es/table-export/excel/index.d.ts +4 -0
- package/es/table-export/excel/index.js +69 -33
- package/es/table-export/excel/index.js.map +1 -1
- package/es/table-export/index.d.ts +2 -2
- package/es/table-export/index.js +2 -2
- package/es/table-export/index.js.map +1 -1
- package/es/table-export.js +5 -2
- package/es/table-export.js.map +1 -1
- package/es/table-series-number.js +1 -0
- package/es/table-series-number.js.map +1 -1
- package/package.json +8 -8
package/dist/vtable-plugins.js
CHANGED
|
@@ -8622,12 +8622,304 @@
|
|
|
8622
8622
|
* @copyright Louis-Dominique Dubeau
|
|
8623
8623
|
*/function n(e){return e>=65&&e<=90||95===e||e>=97&&e<=122||e>=192&&e<=214||e>=216&&e<=246||e>=248&&e<=767||e>=880&&e<=893||e>=895&&e<=8191||e>=8204&&e<=8205||e>=8304&&e<=8591||e>=11264&&e<=12271||e>=12289&&e<=55295||e>=63744&&e<=64975||e>=65008&&e<=65533||e>=65536&&e<=983039;}Object.defineProperty(r,"__esModule",{value:!0}),r.NC_NAME_START_CHAR="A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd\ud800\udc00-\udb7f\udfff",r.NC_NAME_CHAR="-"+r.NC_NAME_START_CHAR+".0-9\xb7\u0300-\u036f\u203f-\u2040",r.NC_NAME_START_CHAR_RE=new RegExp("^["+r.NC_NAME_START_CHAR+"]$","u"),r.NC_NAME_CHAR_RE=new RegExp("^["+r.NC_NAME_CHAR+"]$","u"),r.NC_NAME_RE=new RegExp("^["+r.NC_NAME_START_CHAR+"]["+r.NC_NAME_CHAR+"]*$","u"),r.isNCNameStartChar=n,r.isNCNameChar=function(e){return n(e)||45===e||46===e||e>=48&&e<=57||183===e||e>=768&&e<=879||e>=8255&&e<=8256;};},{}]},{},[15])(15);});})(exceljs_min);var exceljs_minExports=exceljs_min.exports;var ExcelJS = /*@__PURE__*/getDefaultExportFromCjs(exceljs_minExports);
|
|
8624
8624
|
|
|
8625
|
+
async function importCsvFile(file, options) {
|
|
8626
|
+
const text = await file.text();
|
|
8627
|
+
const delimiter = options?.delimiter || ',';
|
|
8628
|
+
const lines = text.split(/\r?\n/).filter(line => line.trim().length > 0);
|
|
8629
|
+
if (lines.length === 0) {
|
|
8630
|
+
throw new Error('CSV 文件为空');
|
|
8631
|
+
}
|
|
8632
|
+
const data = [];
|
|
8633
|
+
for (const line of lines) {
|
|
8634
|
+
const row = parseCsvLine(line, delimiter);
|
|
8635
|
+
data.push(row);
|
|
8636
|
+
}
|
|
8637
|
+
const rowCount = data.length;
|
|
8638
|
+
const columnCount = Math.max(...data.map(row => row.length), 0);
|
|
8639
|
+
const sheetTitle = file.name.replace(/\.(csv|txt)$/i, '') || 'Sheet1';
|
|
8640
|
+
const sheetKey = `sheet_${Date.now()}_0`;
|
|
8641
|
+
const sheetData = {
|
|
8642
|
+
sheetTitle,
|
|
8643
|
+
sheetKey,
|
|
8644
|
+
data,
|
|
8645
|
+
columnCount,
|
|
8646
|
+
rowCount
|
|
8647
|
+
};
|
|
8648
|
+
return {
|
|
8649
|
+
sheets: [sheetData]
|
|
8650
|
+
};
|
|
8651
|
+
}
|
|
8652
|
+
function parseCsvLine(line, delimiter) {
|
|
8653
|
+
const result = [];
|
|
8654
|
+
let current = '';
|
|
8655
|
+
let inQuotes = false;
|
|
8656
|
+
for (let i = 0; i < line.length; i++) {
|
|
8657
|
+
const char = line[i];
|
|
8658
|
+
const nextChar = line[i + 1];
|
|
8659
|
+
if (char === '"') {
|
|
8660
|
+
if (inQuotes && nextChar === '"') {
|
|
8661
|
+
current += '"';
|
|
8662
|
+
i++;
|
|
8663
|
+
}
|
|
8664
|
+
else {
|
|
8665
|
+
inQuotes = !inQuotes;
|
|
8666
|
+
}
|
|
8667
|
+
}
|
|
8668
|
+
else if (char === delimiter && !inQuotes) {
|
|
8669
|
+
result.push(current.trim());
|
|
8670
|
+
current = '';
|
|
8671
|
+
}
|
|
8672
|
+
else {
|
|
8673
|
+
current += char;
|
|
8674
|
+
}
|
|
8675
|
+
}
|
|
8676
|
+
result.push(current.trim());
|
|
8677
|
+
return result;
|
|
8678
|
+
}
|
|
8679
|
+
async function importExcelMultipleSheets(file, options) {
|
|
8680
|
+
const workbook = new ExcelJS.Workbook();
|
|
8681
|
+
await workbook.xlsx.load(await file.arrayBuffer());
|
|
8682
|
+
if (!workbook.worksheets || workbook.worksheets.length === 0) {
|
|
8683
|
+
throw new Error('Excel 文件无有效工作表');
|
|
8684
|
+
}
|
|
8685
|
+
let sheetIndices;
|
|
8686
|
+
if (options?.sheetIndices && options.sheetIndices.length > 0) {
|
|
8687
|
+
sheetIndices = options.sheetIndices.filter(index => index >= 0 && index < workbook.worksheets.length);
|
|
8688
|
+
}
|
|
8689
|
+
else {
|
|
8690
|
+
sheetIndices = Array.from({ length: workbook.worksheets.length }, (_, i) => i);
|
|
8691
|
+
}
|
|
8692
|
+
const sheets = [];
|
|
8693
|
+
for (const sheetIndex of sheetIndices) {
|
|
8694
|
+
const worksheet = workbook.worksheets[sheetIndex];
|
|
8695
|
+
if (!worksheet) {
|
|
8696
|
+
continue;
|
|
8697
|
+
}
|
|
8698
|
+
try {
|
|
8699
|
+
const sheetData = await parseWorksheetToSheetData(worksheet, sheetIndex, options);
|
|
8700
|
+
sheets.push(sheetData);
|
|
8701
|
+
}
|
|
8702
|
+
catch (error) {
|
|
8703
|
+
}
|
|
8704
|
+
}
|
|
8705
|
+
if (sheets.length === 0) {
|
|
8706
|
+
throw new Error('没有成功解析任何工作表');
|
|
8707
|
+
}
|
|
8708
|
+
return { sheets };
|
|
8709
|
+
}
|
|
8710
|
+
async function parseWorksheetToSheetData(worksheet, sheetIndex, options) {
|
|
8711
|
+
const sheetTitle = worksheet.name || `Sheet${sheetIndex + 1}`;
|
|
8712
|
+
const sheetKey = `sheet_${Date.now()}_${sheetIndex}`;
|
|
8713
|
+
const rowCount = worksheet.actualRowCount || 0;
|
|
8714
|
+
const columnCount = worksheet.actualColumnCount || 0;
|
|
8715
|
+
if (rowCount === 0 || columnCount === 0) {
|
|
8716
|
+
const cellMerge = parseMergedCells(worksheet, []);
|
|
8717
|
+
return {
|
|
8718
|
+
sheetTitle,
|
|
8719
|
+
sheetKey,
|
|
8720
|
+
data: [],
|
|
8721
|
+
columnCount: 0,
|
|
8722
|
+
rowCount: 0,
|
|
8723
|
+
...(cellMerge.length > 0 ? { cellMerge } : {})
|
|
8724
|
+
};
|
|
8725
|
+
}
|
|
8726
|
+
const data = [];
|
|
8727
|
+
for (let rowNumber = 1; rowNumber <= rowCount; rowNumber++) {
|
|
8728
|
+
const row = worksheet.getRow(rowNumber);
|
|
8729
|
+
const rowData = [];
|
|
8730
|
+
for (let colNumber = 1; colNumber <= columnCount; colNumber++) {
|
|
8731
|
+
const cell = row.getCell(colNumber);
|
|
8732
|
+
let cellValue = cell.value;
|
|
8733
|
+
if (cellValue && typeof cellValue === 'object') {
|
|
8734
|
+
if ('richText' in cellValue) {
|
|
8735
|
+
cellValue = cellValue.richText
|
|
8736
|
+
.map((rt) => rt.text)
|
|
8737
|
+
.join('');
|
|
8738
|
+
}
|
|
8739
|
+
else if ('result' in cellValue) {
|
|
8740
|
+
cellValue = cellValue.result;
|
|
8741
|
+
}
|
|
8742
|
+
else if ('text' in cellValue && 'hyperlink' in cellValue) {
|
|
8743
|
+
cellValue = cellValue.text;
|
|
8744
|
+
}
|
|
8745
|
+
else if (cellValue instanceof Date) {
|
|
8746
|
+
cellValue = cellValue.toISOString();
|
|
8747
|
+
}
|
|
8748
|
+
}
|
|
8749
|
+
rowData.push(cellValue ?? null);
|
|
8750
|
+
}
|
|
8751
|
+
data.push(rowData);
|
|
8752
|
+
}
|
|
8753
|
+
const cellMerge = parseMergedCells(worksheet, data);
|
|
8754
|
+
return {
|
|
8755
|
+
sheetTitle,
|
|
8756
|
+
sheetKey,
|
|
8757
|
+
data,
|
|
8758
|
+
columnCount,
|
|
8759
|
+
rowCount,
|
|
8760
|
+
...(cellMerge.length > 0 ? { cellMerge } : {})
|
|
8761
|
+
};
|
|
8762
|
+
}
|
|
8763
|
+
function parseMergedCells(worksheet, data) {
|
|
8764
|
+
const cellMerge = [];
|
|
8765
|
+
try {
|
|
8766
|
+
const worksheetAny = worksheet;
|
|
8767
|
+
const merges = worksheetAny.model?.merges ||
|
|
8768
|
+
worksheetAny._merges ||
|
|
8769
|
+
{};
|
|
8770
|
+
for (const [masterCell, range] of Object.entries(merges)) {
|
|
8771
|
+
try {
|
|
8772
|
+
let startCol;
|
|
8773
|
+
let startRow;
|
|
8774
|
+
let endCol;
|
|
8775
|
+
let endRow;
|
|
8776
|
+
if (typeof range === 'string') {
|
|
8777
|
+
const rangeMatch = range.match(/^([A-Z]+\d+):([A-Z]+\d+)$/i);
|
|
8778
|
+
if (!rangeMatch) {
|
|
8779
|
+
continue;
|
|
8780
|
+
}
|
|
8781
|
+
const startAddr = parseCellAddress(rangeMatch[1]);
|
|
8782
|
+
const endAddr = parseCellAddress(rangeMatch[2]);
|
|
8783
|
+
if (!startAddr || !endAddr) {
|
|
8784
|
+
continue;
|
|
8785
|
+
}
|
|
8786
|
+
startCol = startAddr.col;
|
|
8787
|
+
startRow = startAddr.row;
|
|
8788
|
+
endCol = endAddr.col;
|
|
8789
|
+
endRow = endAddr.row;
|
|
8790
|
+
}
|
|
8791
|
+
else if (typeof range === 'object' && range !== null) {
|
|
8792
|
+
const rangeObj = range;
|
|
8793
|
+
if (rangeObj.tl && rangeObj.br) {
|
|
8794
|
+
const startAddr = parseCellAddress(rangeObj.tl);
|
|
8795
|
+
const endAddr = parseCellAddress(rangeObj.br);
|
|
8796
|
+
if (!startAddr || !endAddr) {
|
|
8797
|
+
continue;
|
|
8798
|
+
}
|
|
8799
|
+
startCol = startAddr.col;
|
|
8800
|
+
startRow = startAddr.row;
|
|
8801
|
+
endCol = endAddr.col;
|
|
8802
|
+
endRow = endAddr.row;
|
|
8803
|
+
}
|
|
8804
|
+
else if (typeof rangeObj.top === 'number' &&
|
|
8805
|
+
typeof rangeObj.left === 'number' &&
|
|
8806
|
+
typeof rangeObj.bottom === 'number' &&
|
|
8807
|
+
typeof rangeObj.right === 'number') {
|
|
8808
|
+
startRow = rangeObj.top - 1;
|
|
8809
|
+
startCol = rangeObj.left - 1;
|
|
8810
|
+
endRow = rangeObj.bottom - 1;
|
|
8811
|
+
endCol = rangeObj.right - 1;
|
|
8812
|
+
}
|
|
8813
|
+
else {
|
|
8814
|
+
continue;
|
|
8815
|
+
}
|
|
8816
|
+
}
|
|
8817
|
+
else {
|
|
8818
|
+
continue;
|
|
8819
|
+
}
|
|
8820
|
+
let text;
|
|
8821
|
+
if (startRow >= 0 && startRow < data.length && startCol >= 0 && startCol < data[startRow].length) {
|
|
8822
|
+
const cellValue = data[startRow][startCol];
|
|
8823
|
+
if (cellValue !== null && cellValue !== undefined) {
|
|
8824
|
+
text = String(cellValue);
|
|
8825
|
+
}
|
|
8826
|
+
}
|
|
8827
|
+
cellMerge.push({
|
|
8828
|
+
text,
|
|
8829
|
+
range: {
|
|
8830
|
+
start: {
|
|
8831
|
+
col: startCol,
|
|
8832
|
+
row: startRow
|
|
8833
|
+
},
|
|
8834
|
+
end: {
|
|
8835
|
+
col: endCol,
|
|
8836
|
+
row: endRow
|
|
8837
|
+
},
|
|
8838
|
+
isCustom: true
|
|
8839
|
+
}
|
|
8840
|
+
});
|
|
8841
|
+
}
|
|
8842
|
+
catch (error) {
|
|
8843
|
+
}
|
|
8844
|
+
}
|
|
8845
|
+
}
|
|
8846
|
+
catch (error) {
|
|
8847
|
+
}
|
|
8848
|
+
return cellMerge;
|
|
8849
|
+
}
|
|
8850
|
+
function parseCellAddress(address) {
|
|
8851
|
+
try {
|
|
8852
|
+
const match = address.match(/^([A-Z]+)(\d+)$/i);
|
|
8853
|
+
if (!match) {
|
|
8854
|
+
return null;
|
|
8855
|
+
}
|
|
8856
|
+
const colLetters = match[1].toUpperCase();
|
|
8857
|
+
const rowNumber = parseInt(match[2], 10);
|
|
8858
|
+
let col = 0;
|
|
8859
|
+
for (let i = 0; i < colLetters.length; i++) {
|
|
8860
|
+
col = col * 26 + (colLetters.charCodeAt(i) - 64);
|
|
8861
|
+
}
|
|
8862
|
+
col = col - 1;
|
|
8863
|
+
const row = rowNumber - 1;
|
|
8864
|
+
return { col, row };
|
|
8865
|
+
}
|
|
8866
|
+
catch (error) {
|
|
8867
|
+
return null;
|
|
8868
|
+
}
|
|
8869
|
+
}
|
|
8870
|
+
|
|
8871
|
+
function applyImportToVTableSheet(vtableSheetInstance, result, options) {
|
|
8872
|
+
const clearExisting = options?.clearExisting !== false;
|
|
8873
|
+
if (result.sheets.length === 0) {
|
|
8874
|
+
return;
|
|
8875
|
+
}
|
|
8876
|
+
if (typeof vtableSheetInstance.addSheet !== 'function') {
|
|
8877
|
+
throw new Error('VTableSheet 实例方法不完整');
|
|
8878
|
+
}
|
|
8879
|
+
const existingSheets = clearExisting ? [...vtableSheetInstance.getAllSheets()] : [];
|
|
8880
|
+
const existingSheetKeys = existingSheets.map((s) => s.sheetKey);
|
|
8881
|
+
const importedSheetKeys = [];
|
|
8882
|
+
for (let i = 0; i < result.sheets.length; i++) {
|
|
8883
|
+
const sheetData = result.sheets[i];
|
|
8884
|
+
let sheetKey = sheetData.sheetKey;
|
|
8885
|
+
let suffix = 1;
|
|
8886
|
+
while (vtableSheetInstance.getSheet(sheetKey) || importedSheetKeys.includes(sheetKey)) {
|
|
8887
|
+
sheetKey = `${sheetData.sheetKey}_${suffix}`;
|
|
8888
|
+
suffix++;
|
|
8889
|
+
}
|
|
8890
|
+
const sheetDefine = {
|
|
8891
|
+
sheetKey: sheetKey,
|
|
8892
|
+
sheetTitle: sheetData.sheetTitle,
|
|
8893
|
+
data: sheetData.data,
|
|
8894
|
+
rowCount: Math.max(sheetData.rowCount, 100),
|
|
8895
|
+
columnCount: Math.max(sheetData.columnCount, 26),
|
|
8896
|
+
cellMerge: sheetData.cellMerge,
|
|
8897
|
+
active: false
|
|
8898
|
+
};
|
|
8899
|
+
vtableSheetInstance.addSheet(sheetDefine);
|
|
8900
|
+
importedSheetKeys.push(sheetKey);
|
|
8901
|
+
}
|
|
8902
|
+
if (clearExisting && existingSheetKeys.length > 0) {
|
|
8903
|
+
for (const oldSheetKey of existingSheetKeys) {
|
|
8904
|
+
if (importedSheetKeys.includes(oldSheetKey)) {
|
|
8905
|
+
continue;
|
|
8906
|
+
}
|
|
8907
|
+
if (vtableSheetInstance.getSheet(oldSheetKey) && vtableSheetInstance.getSheetCount() > 1) {
|
|
8908
|
+
vtableSheetInstance.removeSheet(oldSheetKey);
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
}
|
|
8912
|
+
if (importedSheetKeys.length > 0) {
|
|
8913
|
+
vtableSheetInstance.activateSheet(importedSheetKeys[0]);
|
|
8914
|
+
}
|
|
8915
|
+
}
|
|
8916
|
+
|
|
8625
8917
|
class ExcelImportPlugin {
|
|
8626
8918
|
id = `excel-import-plugin`;
|
|
8627
8919
|
name = 'ExcelImportPlugin';
|
|
8628
8920
|
runTime = [VTable.TABLE_EVENT_TYPE.INITIALIZED];
|
|
8629
8921
|
options;
|
|
8630
|
-
|
|
8922
|
+
table = null;
|
|
8631
8923
|
constructor(options) {
|
|
8632
8924
|
this.options = {
|
|
8633
8925
|
autoTable: true,
|
|
@@ -8637,6 +8929,8 @@
|
|
|
8637
8929
|
batchSize: 1000,
|
|
8638
8930
|
enableBatchProcessing: true,
|
|
8639
8931
|
asyncDelay: 5,
|
|
8932
|
+
importAllSheets: false,
|
|
8933
|
+
clearExisting: true,
|
|
8640
8934
|
...options
|
|
8641
8935
|
};
|
|
8642
8936
|
if (options?.id) {
|
|
@@ -8644,64 +8938,55 @@
|
|
|
8644
8938
|
}
|
|
8645
8939
|
}
|
|
8646
8940
|
run(...args) {
|
|
8647
|
-
const
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
this.
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
return this._importFromFileDialog(mergedOptions);
|
|
8941
|
+
const runTime = args[1];
|
|
8942
|
+
if (runTime === VTable.TABLE_EVENT_TYPE.INITIALIZED) {
|
|
8943
|
+
this.table = args[2];
|
|
8944
|
+
this.table.importFile = () => {
|
|
8945
|
+
this.import('file');
|
|
8946
|
+
};
|
|
8947
|
+
if (this.table.__vtableSheet) {
|
|
8948
|
+
const vtableSheet = this.table.__vtableSheet;
|
|
8949
|
+
if (!vtableSheet._importFile) {
|
|
8950
|
+
vtableSheet._importFile = async (options) => {
|
|
8951
|
+
const mergedOptions = { ...this.options, ...options };
|
|
8952
|
+
return this._importFileFromDialogForVTableSheet(vtableSheet, mergedOptions);
|
|
8953
|
+
};
|
|
8954
|
+
}
|
|
8955
|
+
}
|
|
8663
8956
|
}
|
|
8664
|
-
|
|
8665
|
-
|
|
8957
|
+
}
|
|
8958
|
+
async _importFile(options) {
|
|
8959
|
+
if (!this.table) {
|
|
8960
|
+
throw new Error('表格实例不存在或已销毁,无法导入数据!');
|
|
8666
8961
|
}
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8962
|
+
const mergedOptions = { ...this.options, ...options };
|
|
8963
|
+
const isVTableSheet = this._detectVTableSheet(this.table);
|
|
8964
|
+
if (isVTableSheet) {
|
|
8965
|
+
return this._importMultipleSheetsFromFileDialog({
|
|
8966
|
+
...mergedOptions,
|
|
8967
|
+
importAllSheets: true
|
|
8968
|
+
});
|
|
8672
8969
|
}
|
|
8673
|
-
throw new Error('
|
|
8970
|
+
throw new Error('ListTable 单 sheet 导入功能需要进一步重构');
|
|
8674
8971
|
}
|
|
8675
|
-
|
|
8972
|
+
_selectFile(accept = '.xlsx,.xls,.csv,.txt,.json,.html,.htm') {
|
|
8676
8973
|
return new Promise((resolve, reject) => {
|
|
8677
|
-
if (!this._tableInstance) {
|
|
8678
|
-
reject(new Error('表格实例不存在或已销毁,无法导入数据!'));
|
|
8679
|
-
return;
|
|
8680
|
-
}
|
|
8681
8974
|
const input = document.createElement('input');
|
|
8682
8975
|
input.type = 'file';
|
|
8976
|
+
input.accept = accept;
|
|
8683
8977
|
input.style.display = 'none';
|
|
8684
8978
|
document.body.appendChild(input);
|
|
8685
|
-
input.addEventListener('change',
|
|
8979
|
+
input.addEventListener('change', () => {
|
|
8686
8980
|
try {
|
|
8687
|
-
const file =
|
|
8981
|
+
const file = input.files?.[0];
|
|
8688
8982
|
if (!file) {
|
|
8689
8983
|
document.body.removeChild(input);
|
|
8690
8984
|
reject(new Error('未选择文件'));
|
|
8691
8985
|
return;
|
|
8692
8986
|
}
|
|
8693
|
-
const result = await this._parseFile(file, options);
|
|
8694
|
-
if (options.autoTable && this._tableInstance) {
|
|
8695
|
-
if (options.autoColumns) {
|
|
8696
|
-
this._tableInstance.updateOption(Object.assign({}, this._tableInstance.options, {
|
|
8697
|
-
columns: result.columns
|
|
8698
|
-
}));
|
|
8699
|
-
}
|
|
8700
|
-
this._tableInstance.setRecords(result.records);
|
|
8701
|
-
}
|
|
8702
8987
|
input.value = '';
|
|
8703
8988
|
document.body.removeChild(input);
|
|
8704
|
-
resolve(
|
|
8989
|
+
resolve(file);
|
|
8705
8990
|
}
|
|
8706
8991
|
catch (error) {
|
|
8707
8992
|
document.body.removeChild(input);
|
|
@@ -8711,6 +8996,116 @@
|
|
|
8711
8996
|
input.click();
|
|
8712
8997
|
});
|
|
8713
8998
|
}
|
|
8999
|
+
async _importFileFromDialogForVTableSheet(vtableSheetInstance, options) {
|
|
9000
|
+
try {
|
|
9001
|
+
const file = await this._selectFile('.xlsx,.xls,.csv,.txt');
|
|
9002
|
+
const fileExtension = this._getFileExtension(file.name).toLowerCase();
|
|
9003
|
+
let result;
|
|
9004
|
+
if (fileExtension === 'csv' || fileExtension === 'txt') {
|
|
9005
|
+
result = await importCsvFile(file, options);
|
|
9006
|
+
}
|
|
9007
|
+
else if (fileExtension === 'xlsx' || fileExtension === 'xls') {
|
|
9008
|
+
result = await importExcelMultipleSheets(file, options);
|
|
9009
|
+
}
|
|
9010
|
+
else {
|
|
9011
|
+
throw new Error('不支持的文件类型,仅支持 Excel (.xlsx, .xls) 和 CSV (.csv, .txt)');
|
|
9012
|
+
}
|
|
9013
|
+
if (options.autoTable !== false && result.sheets.length > 0) {
|
|
9014
|
+
applyImportToVTableSheet(vtableSheetInstance, result, options);
|
|
9015
|
+
}
|
|
9016
|
+
return result;
|
|
9017
|
+
}
|
|
9018
|
+
catch (error) {
|
|
9019
|
+
throw error;
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
9022
|
+
async _importMultipleSheetsFromFileDialog(options) {
|
|
9023
|
+
try {
|
|
9024
|
+
const file = await this._selectFile('.xlsx,.xls,.csv,.txt');
|
|
9025
|
+
const fileExtension = this._getFileExtension(file.name).toLowerCase();
|
|
9026
|
+
let result;
|
|
9027
|
+
if (fileExtension === 'csv' || fileExtension === 'txt') {
|
|
9028
|
+
result = await importCsvFile(file, options);
|
|
9029
|
+
}
|
|
9030
|
+
else if (fileExtension === 'xlsx' || fileExtension === 'xls') {
|
|
9031
|
+
result = await importExcelMultipleSheets(file, options);
|
|
9032
|
+
}
|
|
9033
|
+
else {
|
|
9034
|
+
throw new Error('不支持的文件类型,仅支持 Excel (.xlsx, .xls) 和 CSV (.csv, .txt)');
|
|
9035
|
+
}
|
|
9036
|
+
if (options.autoTable !== false && this.table && this._detectVTableSheet(this.table)) {
|
|
9037
|
+
const vtableSheet = this.table.__vtableSheet;
|
|
9038
|
+
if (vtableSheet) {
|
|
9039
|
+
applyImportToVTableSheet(vtableSheet, result, options);
|
|
9040
|
+
}
|
|
9041
|
+
}
|
|
9042
|
+
return result;
|
|
9043
|
+
}
|
|
9044
|
+
catch (error) {
|
|
9045
|
+
throw error;
|
|
9046
|
+
}
|
|
9047
|
+
}
|
|
9048
|
+
_detectVTableSheet(instance) {
|
|
9049
|
+
const inst = instance;
|
|
9050
|
+
return !!(inst &&
|
|
9051
|
+
typeof inst.updateOption === 'function' &&
|
|
9052
|
+
inst.options &&
|
|
9053
|
+
typeof inst.options === 'object' &&
|
|
9054
|
+
inst.options !== null &&
|
|
9055
|
+
Array.isArray(inst.options.sheets));
|
|
9056
|
+
}
|
|
9057
|
+
_getFileExtension(filename) {
|
|
9058
|
+
const parts = filename.split('.');
|
|
9059
|
+
return parts.length > 1 ? parts[parts.length - 1] : '';
|
|
9060
|
+
}
|
|
9061
|
+
release() {
|
|
9062
|
+
if (this.table) {
|
|
9063
|
+
delete this.table.importFile;
|
|
9064
|
+
this.table = null;
|
|
9065
|
+
}
|
|
9066
|
+
}
|
|
9067
|
+
async import(type, source, options) {
|
|
9068
|
+
if (!this.table) {
|
|
9069
|
+
throw new Error('表格实例不存在或已销毁,无法导入数据!');
|
|
9070
|
+
}
|
|
9071
|
+
const mergedOptions = { ...this.options, ...options };
|
|
9072
|
+
const isVTableSheet = this._detectVTableSheet(this.table);
|
|
9073
|
+
if (isVTableSheet && type === 'file') {
|
|
9074
|
+
return this._importMultipleSheetsFromFileDialog({
|
|
9075
|
+
...mergedOptions,
|
|
9076
|
+
importAllSheets: true
|
|
9077
|
+
});
|
|
9078
|
+
}
|
|
9079
|
+
if (type === 'file') {
|
|
9080
|
+
return this._importFromFileDialog(mergedOptions);
|
|
9081
|
+
}
|
|
9082
|
+
if (typeof source === 'string') {
|
|
9083
|
+
return this._importFromString(type, source, mergedOptions);
|
|
9084
|
+
}
|
|
9085
|
+
if (Array.isArray(source) || typeof source === 'object') {
|
|
9086
|
+
if (type !== 'json') {
|
|
9087
|
+
throw new Error('只有JSON格式支持从对象导入');
|
|
9088
|
+
}
|
|
9089
|
+
return this._importFromData('json', source, mergedOptions);
|
|
9090
|
+
}
|
|
9091
|
+
throw new Error('Invalid import source');
|
|
9092
|
+
}
|
|
9093
|
+
async _importFromFileDialog(options) {
|
|
9094
|
+
if (!this.table) {
|
|
9095
|
+
throw new Error('表格实例不存在或已销毁,无法导入数据!');
|
|
9096
|
+
}
|
|
9097
|
+
const file = await this._selectFile();
|
|
9098
|
+
const result = await this._parseFile(file, options);
|
|
9099
|
+
if (options.autoTable && this.table) {
|
|
9100
|
+
if (options.autoColumns) {
|
|
9101
|
+
this.table.updateOption(Object.assign({}, this.table.options, {
|
|
9102
|
+
columns: result.columns
|
|
9103
|
+
}));
|
|
9104
|
+
}
|
|
9105
|
+
this.table.setRecords(result.records);
|
|
9106
|
+
}
|
|
9107
|
+
return result;
|
|
9108
|
+
}
|
|
8714
9109
|
async _importFromString(type, data, options) {
|
|
8715
9110
|
let result;
|
|
8716
9111
|
switch (type) {
|
|
@@ -8726,14 +9121,14 @@
|
|
|
8726
9121
|
default:
|
|
8727
9122
|
throw new Error(`不支持的导入类型: ${type}`);
|
|
8728
9123
|
}
|
|
8729
|
-
if (options.autoTable && this.
|
|
9124
|
+
if (options.autoTable && this.table) {
|
|
8730
9125
|
if (options.autoColumns) {
|
|
8731
|
-
this.
|
|
9126
|
+
this.table.updateOption({
|
|
8732
9127
|
columns: result.columns,
|
|
8733
9128
|
plugins: [this]
|
|
8734
9129
|
});
|
|
8735
9130
|
}
|
|
8736
|
-
this.
|
|
9131
|
+
this.table.setRecords(result.records);
|
|
8737
9132
|
}
|
|
8738
9133
|
return result;
|
|
8739
9134
|
}
|
|
@@ -8745,14 +9140,14 @@
|
|
|
8745
9140
|
else {
|
|
8746
9141
|
throw new Error(`不支持的数据类型: ${type}`);
|
|
8747
9142
|
}
|
|
8748
|
-
if (options.autoTable && this.
|
|
9143
|
+
if (options.autoTable && this.table) {
|
|
8749
9144
|
if (options.autoColumns) {
|
|
8750
|
-
this.
|
|
9145
|
+
this.table.updateOption({
|
|
8751
9146
|
columns: result.columns,
|
|
8752
9147
|
plugins: [this]
|
|
8753
9148
|
});
|
|
8754
9149
|
}
|
|
8755
|
-
this.
|
|
9150
|
+
this.table.setRecords(result.records);
|
|
8756
9151
|
}
|
|
8757
9152
|
return result;
|
|
8758
9153
|
}
|
|
@@ -8774,10 +9169,6 @@
|
|
|
8774
9169
|
throw new Error(`不支持的文件类型: ${fileExtension}`);
|
|
8775
9170
|
}
|
|
8776
9171
|
}
|
|
8777
|
-
_getFileExtension(filename) {
|
|
8778
|
-
const parts = filename.split('.');
|
|
8779
|
-
return parts.length > 1 ? parts[parts.length - 1] : '';
|
|
8780
|
-
}
|
|
8781
9172
|
async _parseExcelFile(file, options) {
|
|
8782
9173
|
const mergedOptions = { ...this.options, ...options };
|
|
8783
9174
|
return await ExcelImportPlugin.importExcelToVTableData(file, mergedOptions);
|
|
@@ -8934,16 +9325,40 @@
|
|
|
8934
9325
|
return columns;
|
|
8935
9326
|
}
|
|
8936
9327
|
async _parseCSVString(text, options) {
|
|
8937
|
-
const
|
|
9328
|
+
const delimiter = options.delimiter || ',';
|
|
9329
|
+
const lines = text.split(/\r?\n/).filter(line => line.trim().length > 0);
|
|
8938
9330
|
if (lines.length === 0) {
|
|
8939
9331
|
throw new Error('CSV文件为空');
|
|
8940
9332
|
}
|
|
8941
|
-
const delimiter = options.delimiter || ',';
|
|
8942
9333
|
const parseCSVLine = (line) => {
|
|
8943
|
-
|
|
9334
|
+
const result = [];
|
|
9335
|
+
let current = '';
|
|
9336
|
+
let inQuotes = false;
|
|
9337
|
+
for (let i = 0; i < line.length; i++) {
|
|
9338
|
+
const char = line[i];
|
|
9339
|
+
const nextChar = line[i + 1];
|
|
9340
|
+
if (char === '"') {
|
|
9341
|
+
if (inQuotes && nextChar === '"') {
|
|
9342
|
+
current += '"';
|
|
9343
|
+
i++;
|
|
9344
|
+
}
|
|
9345
|
+
else {
|
|
9346
|
+
inQuotes = !inQuotes;
|
|
9347
|
+
}
|
|
9348
|
+
}
|
|
9349
|
+
else if (char === delimiter && !inQuotes) {
|
|
9350
|
+
result.push(current.trim());
|
|
9351
|
+
current = '';
|
|
9352
|
+
}
|
|
9353
|
+
else {
|
|
9354
|
+
current += char;
|
|
9355
|
+
}
|
|
9356
|
+
}
|
|
9357
|
+
result.push(current.trim());
|
|
9358
|
+
return result;
|
|
8944
9359
|
};
|
|
8945
9360
|
const headerRowCount = 1;
|
|
8946
|
-
const headerRows = lines.slice(0, headerRowCount).map(parseCSVLine);
|
|
9361
|
+
const headerRows = lines.slice(0, headerRowCount).map(line => parseCSVLine(line).map(cell => String(cell || '')));
|
|
8947
9362
|
const dataRows = lines.slice(headerRowCount);
|
|
8948
9363
|
const columns = this._buildColumnsFromHeaders(headerRows);
|
|
8949
9364
|
const records = [];
|
|
@@ -8952,7 +9367,7 @@
|
|
|
8952
9367
|
const parsedRow = parseCSVLine(line);
|
|
8953
9368
|
const record = {};
|
|
8954
9369
|
parsedRow.forEach((cell, i) => {
|
|
8955
|
-
record[`col${i}`] = cell
|
|
9370
|
+
record[`col${i}`] = cell ?? '';
|
|
8956
9371
|
});
|
|
8957
9372
|
return record;
|
|
8958
9373
|
});
|
|
@@ -9098,17 +9513,17 @@
|
|
|
9098
9513
|
};
|
|
9099
9514
|
const columnsStr = columns.map(col => formatColumn(col)).join(',\n');
|
|
9100
9515
|
const recordsStr = records.map(formatRecord).join(',\n');
|
|
9101
|
-
return `// VTable 数据导出 - JavaScript 对象字面量格式
|
|
9102
|
-
// 生成时间: ${new Date().toLocaleString()}
|
|
9103
|
-
|
|
9104
|
-
const vtableData = {
|
|
9105
|
-
columns: [
|
|
9106
|
-
${columnsStr}
|
|
9107
|
-
],
|
|
9108
|
-
records: [
|
|
9109
|
-
${recordsStr}
|
|
9110
|
-
]
|
|
9111
|
-
};
|
|
9516
|
+
return `// VTable 数据导出 - JavaScript 对象字面量格式
|
|
9517
|
+
// 生成时间: ${new Date().toLocaleString()}
|
|
9518
|
+
|
|
9519
|
+
const vtableData = {
|
|
9520
|
+
columns: [
|
|
9521
|
+
${columnsStr}
|
|
9522
|
+
],
|
|
9523
|
+
records: [
|
|
9524
|
+
${recordsStr}
|
|
9525
|
+
]
|
|
9526
|
+
};
|
|
9112
9527
|
`;
|
|
9113
9528
|
}
|
|
9114
9529
|
_exportToJS(columns, records) {
|
|
@@ -9554,6 +9969,10 @@ ${recordsStr}
|
|
|
9554
9969
|
}
|
|
9555
9970
|
}
|
|
9556
9971
|
syncColWidthToComponent() {
|
|
9972
|
+
const colRange = this.table.getBodyVisibleColRange();
|
|
9973
|
+
if (!colRange) {
|
|
9974
|
+
return;
|
|
9975
|
+
}
|
|
9557
9976
|
const { colStart, colEnd } = this.table.getBodyVisibleColRange();
|
|
9558
9977
|
const adjustStartColIndex = colStart;
|
|
9559
9978
|
const adjustEndColIndex = Math.min(colEnd, this.table.scenegraph.proxy.colEnd);
|
|
@@ -10471,9 +10890,7 @@ ${recordsStr}
|
|
|
10471
10890
|
toggleSelectAll(fieldId, selected) {
|
|
10472
10891
|
const options = this.valueFilterOptionList.get(fieldId);
|
|
10473
10892
|
options.forEach(option => {
|
|
10474
|
-
|
|
10475
|
-
option.checkbox.checked = selected;
|
|
10476
|
-
}
|
|
10893
|
+
option.checkbox.checked = selected;
|
|
10477
10894
|
});
|
|
10478
10895
|
}
|
|
10479
10896
|
syncSelectAllCheckbox(fieldId) {
|
|
@@ -11155,6 +11572,7 @@ ${recordsStr}
|
|
|
11155
11572
|
clearFilterOptionLink;
|
|
11156
11573
|
cancelFilterButton;
|
|
11157
11574
|
applyFilterButton;
|
|
11575
|
+
activeType = 'byValue';
|
|
11158
11576
|
constructor(table, filterStateManager, pluginOptions) {
|
|
11159
11577
|
this.table = table;
|
|
11160
11578
|
this.filterStateManager = filterStateManager;
|
|
@@ -11265,12 +11683,20 @@ ${recordsStr}
|
|
|
11265
11683
|
applyStyles(this.applyFilterButton, styles.footerButton(true));
|
|
11266
11684
|
this.valueFilter.updateStyles(styles);
|
|
11267
11685
|
this.conditionFilter.updateStyles(styles);
|
|
11686
|
+
if (this.activeType === 'byCondition') {
|
|
11687
|
+
this.onTabSwitch('byCondition');
|
|
11688
|
+
}
|
|
11689
|
+
else {
|
|
11690
|
+
this.onTabSwitch('byValue');
|
|
11691
|
+
}
|
|
11268
11692
|
}
|
|
11269
11693
|
attachEventListeners() {
|
|
11270
11694
|
this.filterTabByValue.addEventListener('click', () => {
|
|
11695
|
+
this.activeType = 'byValue';
|
|
11271
11696
|
this.onTabSwitch('byValue');
|
|
11272
11697
|
});
|
|
11273
11698
|
this.filterTabByCondition.addEventListener('click', () => {
|
|
11699
|
+
this.activeType = 'byCondition';
|
|
11274
11700
|
this.onTabSwitch('byCondition');
|
|
11275
11701
|
});
|
|
11276
11702
|
this.cancelFilterButton.addEventListener('click', () => this.hide());
|
|
@@ -21506,20 +21932,38 @@ ${recordsStr}
|
|
|
21506
21932
|
async function exportVTableToExcel(tableInstance, options, optimization = false) {
|
|
21507
21933
|
const workbook = new ExcelJS.Workbook();
|
|
21508
21934
|
const worksheet = workbook.addWorksheet('sheet1');
|
|
21935
|
+
await renderTableToWorksheet(tableInstance, worksheet, workbook, options, optimization);
|
|
21936
|
+
const buffer = await workbook.xlsx.writeBuffer();
|
|
21937
|
+
return buffer;
|
|
21938
|
+
}
|
|
21939
|
+
async function exportMultipleVTablesToExcel(tables, options, optimization = false) {
|
|
21940
|
+
const workbook = new ExcelJS.Workbook();
|
|
21941
|
+
const usedWorksheetNames = new Set();
|
|
21942
|
+
for (let i = 0; i < tables.length; i++) {
|
|
21943
|
+
const { table, name } = tables[i];
|
|
21944
|
+
const safeName = getUniqueWorksheetName(name || `sheet${i + 1}`, usedWorksheetNames);
|
|
21945
|
+
usedWorksheetNames.add(safeName);
|
|
21946
|
+
const worksheet = workbook.addWorksheet(safeName);
|
|
21947
|
+
await renderTableToWorksheet(table, worksheet, workbook, options, optimization);
|
|
21948
|
+
}
|
|
21949
|
+
const buffer = await workbook.xlsx.writeBuffer();
|
|
21950
|
+
return buffer;
|
|
21951
|
+
}
|
|
21952
|
+
async function renderTableToWorksheet(tableInstance, worksheet, workbook, options, optimization = false) {
|
|
21509
21953
|
const exportAllData = !!options?.exportAllData;
|
|
21510
21954
|
const { handleRowCount, reset } = handlePaginationExport(tableInstance, exportAllData);
|
|
21511
|
-
|
|
21512
|
-
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21955
|
+
try {
|
|
21956
|
+
const minRow = 0;
|
|
21957
|
+
const maxRow = handleRowCount();
|
|
21958
|
+
const minCol = 0;
|
|
21959
|
+
const maxCol = tableInstance.colCount - 1;
|
|
21960
|
+
worksheet.properties.defaultRowHeight = 40;
|
|
21961
|
+
const columns = [];
|
|
21962
|
+
const mergeCells = [];
|
|
21963
|
+
const mergeCellSet = new Set();
|
|
21964
|
+
const SLICE_SIZE = 100;
|
|
21965
|
+
let currentRow = minRow;
|
|
21966
|
+
const processSlice = async (deadline) => {
|
|
21523
21967
|
while (currentRow <= maxRow && (!optimization || deadline?.timeRemaining() > 0)) {
|
|
21524
21968
|
const endRow = Math.min(currentRow + SLICE_SIZE - 1, maxRow);
|
|
21525
21969
|
for (let col = minCol; col <= maxCol; col++) {
|
|
@@ -21546,53 +21990,70 @@ ${recordsStr}
|
|
|
21546
21990
|
}
|
|
21547
21991
|
currentRow = endRow + 1;
|
|
21548
21992
|
}
|
|
21549
|
-
if (currentRow
|
|
21550
|
-
|
|
21551
|
-
}
|
|
21552
|
-
else {
|
|
21553
|
-
let nextDeadline;
|
|
21554
|
-
if (optimization) {
|
|
21555
|
-
nextDeadline = await requestIdleCallbackPromise();
|
|
21556
|
-
}
|
|
21993
|
+
if (currentRow <= maxRow) {
|
|
21994
|
+
const nextDeadline = optimization ? await requestIdleCallbackPromise() : undefined;
|
|
21557
21995
|
await processSlice(nextDeadline);
|
|
21558
|
-
resolve();
|
|
21559
21996
|
}
|
|
21560
|
-
}
|
|
21561
|
-
}
|
|
21562
|
-
await new Promise(async (resolve) => {
|
|
21563
|
-
let deadline;
|
|
21997
|
+
};
|
|
21564
21998
|
if (optimization) {
|
|
21565
|
-
deadline = await requestIdleCallbackPromise();
|
|
21999
|
+
const deadline = await requestIdleCallbackPromise();
|
|
22000
|
+
await processSlice(deadline);
|
|
21566
22001
|
}
|
|
21567
|
-
|
|
21568
|
-
|
|
21569
|
-
|
|
21570
|
-
|
|
21571
|
-
|
|
21572
|
-
|
|
21573
|
-
});
|
|
21574
|
-
const frozenView = [];
|
|
21575
|
-
if (tableInstance.frozenRowCount > 0) {
|
|
21576
|
-
frozenView.push({
|
|
21577
|
-
state: 'frozen',
|
|
21578
|
-
ySplit: tableInstance.frozenRowCount,
|
|
21579
|
-
topLeftCell: encodeCellAddress(0, tableInstance.frozenRowCount)
|
|
22002
|
+
else {
|
|
22003
|
+
await processSlice();
|
|
22004
|
+
}
|
|
22005
|
+
worksheet.columns = columns;
|
|
22006
|
+
mergeCells.forEach(mergeCell => {
|
|
22007
|
+
worksheet.mergeCells(mergeCell.start.row + 1, mergeCell.start.col + 1, mergeCell.end.row + 1, mergeCell.end.col + 1);
|
|
21580
22008
|
});
|
|
22009
|
+
const frozenView = [];
|
|
22010
|
+
if (tableInstance.frozenRowCount > 0) {
|
|
22011
|
+
frozenView.push({
|
|
22012
|
+
state: 'frozen',
|
|
22013
|
+
ySplit: tableInstance.frozenRowCount,
|
|
22014
|
+
topLeftCell: encodeCellAddress(0, tableInstance.frozenRowCount)
|
|
22015
|
+
});
|
|
22016
|
+
}
|
|
22017
|
+
if (tableInstance.frozenColCount > 0) {
|
|
22018
|
+
frozenView.push({
|
|
22019
|
+
state: 'frozen',
|
|
22020
|
+
xSplit: tableInstance.frozenColCount,
|
|
22021
|
+
topLeftCell: encodeCellAddress(tableInstance.frozenColCount, 0)
|
|
22022
|
+
});
|
|
22023
|
+
}
|
|
22024
|
+
worksheet.views = frozenView;
|
|
22025
|
+
if (options?.excelJSWorksheetCallback) {
|
|
22026
|
+
options.excelJSWorksheetCallback(worksheet);
|
|
22027
|
+
}
|
|
21581
22028
|
}
|
|
21582
|
-
|
|
21583
|
-
|
|
21584
|
-
state: 'frozen',
|
|
21585
|
-
xSplit: tableInstance.frozenColCount,
|
|
21586
|
-
topLeftCell: encodeCellAddress(tableInstance.frozenColCount, 0)
|
|
21587
|
-
});
|
|
22029
|
+
finally {
|
|
22030
|
+
reset();
|
|
21588
22031
|
}
|
|
21589
|
-
|
|
21590
|
-
|
|
21591
|
-
|
|
22032
|
+
}
|
|
22033
|
+
function getUniqueWorksheetName(rawName, used) {
|
|
22034
|
+
const cleanedBase = sanitizeWorksheetName(rawName) || 'sheet';
|
|
22035
|
+
if (!used.has(cleanedBase)) {
|
|
22036
|
+
return cleanedBase;
|
|
21592
22037
|
}
|
|
21593
|
-
|
|
21594
|
-
|
|
21595
|
-
|
|
22038
|
+
for (let n = 2; n < 10000; n++) {
|
|
22039
|
+
const suffix = `-${n}`;
|
|
22040
|
+
const baseMax = 31 - suffix.length;
|
|
22041
|
+
const base = cleanedBase.length > baseMax ? cleanedBase.slice(0, baseMax) : cleanedBase;
|
|
22042
|
+
const candidate = `${base}${suffix}`;
|
|
22043
|
+
if (!used.has(candidate)) {
|
|
22044
|
+
return candidate;
|
|
22045
|
+
}
|
|
22046
|
+
}
|
|
22047
|
+
return `${cleanedBase.slice(0, 31 - 6)}-${Date.now().toString().slice(-5)}`;
|
|
22048
|
+
}
|
|
22049
|
+
function sanitizeWorksheetName(name) {
|
|
22050
|
+
const trimmed = (name ?? '').toString().trim();
|
|
22051
|
+
const noInvalidChars = trimmed
|
|
22052
|
+
.replace(/[:\\\/\?\*\[\]]/g, ' ')
|
|
22053
|
+
.replace(/\s+/g, ' ')
|
|
22054
|
+
.trim();
|
|
22055
|
+
const nonEmpty = noInvalidChars || 'sheet';
|
|
22056
|
+
return nonEmpty.length > 31 ? nonEmpty.slice(0, 31) : nonEmpty;
|
|
21596
22057
|
}
|
|
21597
22058
|
async function addCell(col, row, tableInstance, worksheet, workbook, options) {
|
|
21598
22059
|
const { layoutMap } = tableInstance.internalProps;
|
|
@@ -21974,6 +22435,14 @@ ${recordsStr}
|
|
|
21974
22435
|
}
|
|
21975
22436
|
return exportVTableToExcel(this.table, options, this.pluginOptions.exportOnIdle);
|
|
21976
22437
|
};
|
|
22438
|
+
if (this.table.__vtableSheet) {
|
|
22439
|
+
if (!this.table.__vtableSheet._exportMutipleTablesToExcel) {
|
|
22440
|
+
this.table.__vtableSheet._exportMutipleTablesToExcel = async (tables) => {
|
|
22441
|
+
const buffer = (await exportMultipleVTablesToExcel(tables, this.pluginOptions.exportExcelOptions));
|
|
22442
|
+
await downloadExcel(buffer, this.pluginOptions.exportExcelOptions.fileName || 'vtable-sheet-export');
|
|
22443
|
+
};
|
|
22444
|
+
}
|
|
22445
|
+
}
|
|
21977
22446
|
}
|
|
21978
22447
|
}
|
|
21979
22448
|
release() {
|