@microsoft/connected-workbooks 2.1.24-beta → 3.0.0
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/README.md +25 -13
- package/dist/generators.js +1 -1
- package/dist/{GridParser.js → gridParser.js} +18 -8
- package/dist/gridUtils.js +58 -0
- package/dist/index.d.ts +2 -2
- package/dist/src/generators.js +14 -0
- package/dist/src/types.js +28 -0
- package/dist/src/utils/arrayUtils.js +46 -0
- package/dist/src/utils/constants.js +145 -0
- package/dist/src/utils/documentUtils.js +102 -0
- package/dist/src/utils/gridUtils.js +103 -0
- package/dist/src/utils/htmlUtils.js +19 -0
- package/dist/src/utils/index.js +24 -0
- package/dist/src/utils/mashupDocumentParser.js +145 -0
- package/dist/src/utils/pqUtils.js +100 -0
- package/dist/src/utils/tableUtils.js +143 -0
- package/dist/src/utils/xmlInnerPartsUtils.js +227 -0
- package/dist/src/utils/xmlPartsUtils.js +68 -0
- package/dist/src/workbookTemplate.js +7 -0
- package/dist/tests/arrayUtils.test.js +65 -0
- package/dist/tests/documentUtils.test.js +35 -0
- package/dist/tests/gridUtils.test.js +168 -0
- package/dist/tests/htmlUtils.test.js +109 -0
- package/dist/tests/mashupDocumentParser.test.js +59 -0
- package/dist/tests/mocks/PqMock.js +7 -0
- package/dist/tests/mocks/index.js +24 -0
- package/dist/tests/mocks/section1mSimpleQueryMock.js +18 -0
- package/dist/tests/mocks/xmlMocks.js +12 -0
- package/dist/tests/tableUtils.test.js +63 -0
- package/dist/tests/workbookQueryTemplate.test.js +64 -0
- package/dist/tests/workbookTableTemplate.test.js +54 -0
- package/dist/tests/xmlInnerPartsUtils.test.js +51 -0
- package/dist/types.d.ts +4 -1
- package/dist/utils/constants.js +20 -9
- package/dist/utils/documentUtils.js +9 -5
- package/dist/utils/gridUtils.js +103 -0
- package/dist/utils/htmlUtils.js +3 -3
- package/dist/utils/index.js +5 -1
- package/dist/utils/mashupDocumentParser.js +6 -24
- package/dist/utils/pqUtils.js +7 -4
- package/dist/utils/tableUtils.js +18 -19
- package/dist/utils/xmlInnerPartsUtils.js +38 -9
- package/dist/utils/xmlPartsUtils.js +12 -6
- package/dist/workbookManager.d.ts +3 -3
- package/dist/workbookManager.js +17 -22
- package/package.json +5 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT license.
|
|
4
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
5
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
6
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
7
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
8
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
10
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
const mocks_1 = require("./mocks");
|
|
15
|
+
const utils_1 = require("../src/utils");
|
|
16
|
+
describe("Workbook Manager tests", () => {
|
|
17
|
+
const mockConnectionString = `<connections xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:xr16="http://schemas.microsoft.com/office/spreadsheetml/2017/revision16" mc:Ignorable="xr16">
|
|
18
|
+
<connection id="1" xr16:uid="{86BA784C-6640-4989-A85E-EB4966B9E741}" keepAlive="1" name="Query - Query1" description="Connection to the 'Query1' query in the workbook." type="5" refreshedVersion="7" background="1" saveData="1">
|
|
19
|
+
<dbPr connection="Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=Query1;" command="SELECT * FROM [Query1]"/></connection></connections>`;
|
|
20
|
+
test("Connection XML attributes contain new query name", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
const { connectionXmlFileString } = yield utils_1.xmlInnerPartsUtils.updateConnections(mockConnectionString, "newQueryName", true);
|
|
22
|
+
expect(connectionXmlFileString.replace(/ /g, "")).toContain('command="SELECT * FROM [newQueryName]'.replace(/ /g, ""));
|
|
23
|
+
expect(connectionXmlFileString.replace(/ /g, "")).toContain('name="Query - newQueryName"'.replace(/ /g, ""));
|
|
24
|
+
expect(connectionXmlFileString.replace(/ /g, "")).toContain(`description="Connection to the 'newQueryName' query in the workbook."`.replace(/ /g, ""));
|
|
25
|
+
}));
|
|
26
|
+
test("Connection XML attributes contain refreshOnLoad value", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
const { connectionXmlFileString } = yield utils_1.xmlInnerPartsUtils.updateConnections(mockConnectionString, "newQueryName", true);
|
|
28
|
+
expect(connectionXmlFileString.replace(/ /g, "")).toContain('refreshOnLoad="1"');
|
|
29
|
+
}));
|
|
30
|
+
test("SharedStrings XML contains new query name", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const { newSharedStrings } = yield utils_1.xmlInnerPartsUtils.updateSharedStrings('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>Query1</t></si><si><t/></si></sst>', "newQueryName");
|
|
32
|
+
expect(newSharedStrings.replace(/ /g, "")).toContain(mocks_1.sharedStringsXmlMock.replace(/ /g, ""));
|
|
33
|
+
}));
|
|
34
|
+
test("Tests SharedStrings update when XML contains query name", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const { newSharedStrings } = yield utils_1.xmlInnerPartsUtils.updateSharedStrings('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>newQueryName</t></si><si><t/></si></sst>', "newQueryName");
|
|
36
|
+
expect(newSharedStrings.replace(/ /g, "")).toContain(mocks_1.existingSharedStringsXmlMock.replace(/ /g, ""));
|
|
37
|
+
}));
|
|
38
|
+
test("SharedStrings XML returns new index", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const { sharedStringIndex } = yield utils_1.xmlInnerPartsUtils.updateSharedStrings('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>Query1</t></si><si><t/></si></sst>', "newQueryName");
|
|
40
|
+
expect(sharedStringIndex).toEqual(2);
|
|
41
|
+
}));
|
|
42
|
+
test("SharedStrings XML returns existing index", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
const { sharedStringIndex } = yield utils_1.xmlInnerPartsUtils.updateSharedStrings('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>newQueryName</t></si><si><t/></si></sst>', "newQueryName");
|
|
44
|
+
expect(sharedStringIndex).toEqual(1);
|
|
45
|
+
}));
|
|
46
|
+
test("Table XML contains refrshonload value", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const { sharedStringIndex, newSharedStrings } = yield utils_1.xmlInnerPartsUtils.updateSharedStrings('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>Query1</t></si><si><t/></si></sst>', "newQueryName");
|
|
48
|
+
expect(sharedStringIndex).toEqual(2);
|
|
49
|
+
expect(newSharedStrings.replace(/ /g, "")).toContain(mocks_1.sharedStringsXmlMock.replace(/ /g, ""));
|
|
50
|
+
}));
|
|
51
|
+
});
|
package/dist/types.d.ts
CHANGED
|
@@ -19,11 +19,14 @@ export interface Metadata {
|
|
|
19
19
|
export interface TableData {
|
|
20
20
|
columnNames: string[];
|
|
21
21
|
rows: string[][];
|
|
22
|
-
columnwidth?: number;
|
|
23
22
|
}
|
|
24
23
|
export interface Grid {
|
|
25
24
|
data: (string | number | boolean)[][];
|
|
25
|
+
config?: GridConfig;
|
|
26
|
+
}
|
|
27
|
+
export interface GridConfig {
|
|
26
28
|
promoteHeaders?: boolean;
|
|
29
|
+
adjustColumnNames?: boolean;
|
|
27
30
|
}
|
|
28
31
|
export interface FileConfigs {
|
|
29
32
|
templateFile?: File;
|
package/dist/utils/constants.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Copyright (c) Microsoft Corporation.
|
|
3
3
|
// Licensed under the MIT license.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.
|
|
6
|
-
exports.URLS = void 0;
|
|
5
|
+
exports.maxQueryLength = exports.divider = exports.section1PathPrefix = exports.emptyValue = exports.falseValue = exports.trueValue = exports.pivotCachesPathPrefix = exports.xmlTextResultType = exports.textResultType = exports.application = exports.uint8ArrayType = exports.blobFileType = exports.relsNotFoundErr = exports.templateFileNotSupportedErr = exports.arrayIsntMxNErr = exports.unexpectedErr = exports.promotedHeadersCannotBeUsedWithoutAdjustingColumnNamesErr = exports.InvalidColumnNameErr = exports.stylesNotFoundErr = exports.EmptyQueryNameErr = exports.QueryNameInvalidCharsErr = exports.QueryNameMaxLengthErr = exports.invalidDataTypeErr = exports.headerNotFoundErr = exports.invalidValueInColumnErr = exports.tableNotFoundErr = exports.queryTableNotFoundErr = exports.templateWithInitialDataErr = exports.formulaSectionNotFoundErr = exports.queryConnectionNotFoundErr = exports.queryAndPivotTableNotFoundErr = exports.queryNameNotFoundErr = exports.emptyQueryMashupErr = exports.base64NotFoundErr = exports.sheetsNotFoundErr = exports.connectionsNotFoundErr = exports.sharedStringsNotFoundErr = exports.docPropsRootElement = exports.docMetadataXmlPath = exports.relsXmlPath = exports.docPropsCoreXmlPath = exports.section1mPath = exports.pivotCachesPath = exports.queryTablesPath = exports.workbookXmlPath = exports.queryTableXmlPath = exports.tableXmlPath = exports.sheetsXmlPath = exports.sharedStringsXmlPath = exports.connectionsXmlPath = void 0;
|
|
6
|
+
exports.URLS = exports.defaults = exports.elementAttributesValues = exports.dataTypeKind = exports.elementAttributes = exports.element = exports.BOM = exports.falseStr = exports.trueStr = void 0;
|
|
7
7
|
exports.connectionsXmlPath = "xl/connections.xml";
|
|
8
8
|
exports.sharedStringsXmlPath = "xl/sharedStrings.xml";
|
|
9
9
|
exports.sheetsXmlPath = "xl/worksheets/sheet1.xml";
|
|
@@ -14,6 +14,8 @@ exports.queryTablesPath = "xl/queryTables/";
|
|
|
14
14
|
exports.pivotCachesPath = "xl/pivotCache/";
|
|
15
15
|
exports.section1mPath = "Formulas/Section1.m";
|
|
16
16
|
exports.docPropsCoreXmlPath = "docProps/core.xml";
|
|
17
|
+
exports.relsXmlPath = "_rels/.rels";
|
|
18
|
+
exports.docMetadataXmlPath = "docMetadata";
|
|
17
19
|
exports.docPropsRootElement = "cp:coreProperties";
|
|
18
20
|
exports.sharedStringsNotFoundErr = "SharedStrings were not found in template";
|
|
19
21
|
exports.connectionsNotFoundErr = "Connections were not found in template";
|
|
@@ -24,16 +26,22 @@ exports.queryNameNotFoundErr = "Query name was not found";
|
|
|
24
26
|
exports.queryAndPivotTableNotFoundErr = "No such query found in Query Table or Pivot Table found in given template";
|
|
25
27
|
exports.queryConnectionNotFoundErr = "No connection found for query";
|
|
26
28
|
exports.formulaSectionNotFoundErr = "Formula section wasn't found in template";
|
|
27
|
-
exports.templateWithInitialDataErr = "Cannot
|
|
29
|
+
exports.templateWithInitialDataErr = "Cannot use a template file with initial data";
|
|
28
30
|
exports.queryTableNotFoundErr = "Query table wasn't found in template";
|
|
29
31
|
exports.tableNotFoundErr = "Table wasn't found in template";
|
|
30
|
-
exports.gridNotFoundErr = "Invalid JSON file, grid data is missing";
|
|
31
32
|
exports.invalidValueInColumnErr = "Invalid cell value in column";
|
|
32
33
|
exports.headerNotFoundErr = "Invalid JSON file, header is missing";
|
|
33
34
|
exports.invalidDataTypeErr = "Invalid JSON file, invalid data type";
|
|
34
35
|
exports.QueryNameMaxLengthErr = "Query names are limited to 80 characters";
|
|
36
|
+
exports.QueryNameInvalidCharsErr = 'Query names cannot contain periods or quotation marks. (. ")';
|
|
35
37
|
exports.EmptyQueryNameErr = "Query name cannot be empty";
|
|
36
38
|
exports.stylesNotFoundErr = "Styles were not found in template";
|
|
39
|
+
exports.InvalidColumnNameErr = "Invalid column name";
|
|
40
|
+
exports.promotedHeadersCannotBeUsedWithoutAdjustingColumnNamesErr = "Headers cannot be promoted without adjusting column names";
|
|
41
|
+
exports.unexpectedErr = "Unexpected error";
|
|
42
|
+
exports.arrayIsntMxNErr = "Array isn't MxN";
|
|
43
|
+
exports.templateFileNotSupportedErr = "Template file is not supported for this API call";
|
|
44
|
+
exports.relsNotFoundErr = ".rels were not found in template";
|
|
37
45
|
exports.blobFileType = "blob";
|
|
38
46
|
exports.uint8ArrayType = "uint8array";
|
|
39
47
|
exports.application = "application/xlsx";
|
|
@@ -48,7 +56,7 @@ exports.divider = "/";
|
|
|
48
56
|
exports.maxQueryLength = 80;
|
|
49
57
|
exports.trueStr = "true";
|
|
50
58
|
exports.falseStr = "false";
|
|
51
|
-
exports.BOM =
|
|
59
|
+
exports.BOM = "\ufeff";
|
|
52
60
|
exports.element = {
|
|
53
61
|
sharedStringTable: "sst",
|
|
54
62
|
text: "t",
|
|
@@ -75,7 +83,8 @@ exports.element = {
|
|
|
75
83
|
sheetData: "sheetData",
|
|
76
84
|
row: "row",
|
|
77
85
|
dimension: "dimension",
|
|
78
|
-
|
|
86
|
+
selection: "selection",
|
|
87
|
+
kindCell: "c",
|
|
79
88
|
};
|
|
80
89
|
exports.elementAttributes = {
|
|
81
90
|
connection: "connection",
|
|
@@ -100,6 +109,7 @@ exports.elementAttributes = {
|
|
|
100
109
|
uniqueName: "uniqueName",
|
|
101
110
|
queryTableFieldId: "queryTableFieldId",
|
|
102
111
|
reference: "ref",
|
|
112
|
+
sqref: "sqref",
|
|
103
113
|
tableColumnId: "tableColumnId",
|
|
104
114
|
nextId: "nextId",
|
|
105
115
|
row: "r",
|
|
@@ -115,13 +125,14 @@ exports.dataTypeKind = {
|
|
|
115
125
|
exports.elementAttributesValues = {
|
|
116
126
|
connectionName: (queryName) => `Query - ${queryName}`,
|
|
117
127
|
connectionDescription: (queryName) => `Connection to the '${queryName}' query in the workbook.`,
|
|
118
|
-
connection: (queryName) => `Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location
|
|
128
|
+
connection: (queryName) => `Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location="${queryName}";`,
|
|
119
129
|
connectionCommand: (queryName) => `SELECT * FROM [${queryName}]`,
|
|
120
|
-
tableResultType: () => "sTable"
|
|
130
|
+
tableResultType: () => "sTable",
|
|
121
131
|
};
|
|
122
132
|
exports.defaults = {
|
|
123
133
|
queryName: "Query1",
|
|
124
|
-
sheetName: "Sheet1"
|
|
134
|
+
sheetName: "Sheet1",
|
|
135
|
+
columnName: "Column",
|
|
125
136
|
};
|
|
126
137
|
exports.URLS = {
|
|
127
138
|
PQ: [
|
|
@@ -59,12 +59,12 @@ const createCellElement = (doc, colIndex, rowIndex, data) => {
|
|
|
59
59
|
const cell = doc.createElementNS(doc.documentElement.namespaceURI, constants_1.element.kindCell);
|
|
60
60
|
cell.setAttribute(constants_1.elementAttributes.row, getCellReferenceRelative(colIndex, rowIndex + 1));
|
|
61
61
|
const cellData = doc.createElementNS(doc.documentElement.namespaceURI, constants_1.element.cellValue);
|
|
62
|
-
updateCellData(data, cell, cellData);
|
|
62
|
+
updateCellData(data, cell, cellData, rowIndex === 0);
|
|
63
63
|
cell.appendChild(cellData);
|
|
64
64
|
return cell;
|
|
65
65
|
};
|
|
66
|
-
const updateCellData = (data, cell, cellData) => {
|
|
67
|
-
switch (resolveType(data)) {
|
|
66
|
+
const updateCellData = (data, cell, cellData, rowHeader) => {
|
|
67
|
+
switch (resolveType(data, rowHeader)) {
|
|
68
68
|
case types_1.DataTypes.string:
|
|
69
69
|
cell.setAttribute(constants_1.element.text, constants_1.dataTypeKind.string);
|
|
70
70
|
break;
|
|
@@ -77,11 +77,15 @@ const updateCellData = (data, cell, cellData) => {
|
|
|
77
77
|
}
|
|
78
78
|
cellData.textContent = data;
|
|
79
79
|
};
|
|
80
|
-
const resolveType = (originalData) => {
|
|
80
|
+
const resolveType = (originalData, rowHeader) => {
|
|
81
81
|
const data = originalData;
|
|
82
|
+
if (rowHeader) {
|
|
83
|
+
// Headers should be string by default.
|
|
84
|
+
return types_1.DataTypes.string;
|
|
85
|
+
}
|
|
82
86
|
let dataType = isNaN(Number(data)) ? types_1.DataTypes.string : types_1.DataTypes.number;
|
|
83
87
|
if (dataType == types_1.DataTypes.string) {
|
|
84
|
-
if (data.
|
|
88
|
+
if (data.trim() == constants_1.trueStr || data.trim() == constants_1.falseStr) {
|
|
85
89
|
dataType = types_1.DataTypes.boolean;
|
|
86
90
|
}
|
|
87
91
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT license.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
const constants_1 = require("../utils/constants");
|
|
6
|
+
const parseToTableData = (grid) => {
|
|
7
|
+
var _a, _b, _c, _d;
|
|
8
|
+
if (grid === null || grid === undefined) {
|
|
9
|
+
grid = { data: [] };
|
|
10
|
+
}
|
|
11
|
+
if (grid.data === null || grid.data === undefined) {
|
|
12
|
+
grid.data = [];
|
|
13
|
+
}
|
|
14
|
+
const mergedGrid = {
|
|
15
|
+
config: {
|
|
16
|
+
promoteHeaders: (_b = (_a = grid.config) === null || _a === void 0 ? void 0 : _a.promoteHeaders) !== null && _b !== void 0 ? _b : false,
|
|
17
|
+
adjustColumnNames: (_d = (_c = grid.config) === null || _c === void 0 ? void 0 : _c.adjustColumnNames) !== null && _d !== void 0 ? _d : true,
|
|
18
|
+
},
|
|
19
|
+
data: grid.data.map((row) => row.map((value) => { var _a; return (_a = value === null || value === void 0 ? void 0 : value.toString()) !== null && _a !== void 0 ? _a : ""; })),
|
|
20
|
+
};
|
|
21
|
+
correctGrid(mergedGrid);
|
|
22
|
+
validateGrid(mergedGrid);
|
|
23
|
+
let columnNames = [];
|
|
24
|
+
if (mergedGrid.config.promoteHeaders && mergedGrid.config.adjustColumnNames) {
|
|
25
|
+
columnNames = getAdjustedColumnNames(mergedGrid.data.shift());
|
|
26
|
+
}
|
|
27
|
+
else if (mergedGrid.config.promoteHeaders && !mergedGrid.config.adjustColumnNames) {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
29
|
+
columnNames = mergedGrid.data.shift();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
columnNames = Array.from({ length: mergedGrid.data[0].length }, (_, index) => `${constants_1.defaults.columnName} ${index + 1}`);
|
|
33
|
+
}
|
|
34
|
+
return { columnNames: columnNames, rows: mergedGrid.data };
|
|
35
|
+
};
|
|
36
|
+
const correctGrid = (grid) => {
|
|
37
|
+
if (grid.data.length === 0) {
|
|
38
|
+
// empty grid fix
|
|
39
|
+
grid.config.promoteHeaders = false;
|
|
40
|
+
grid.data.push([""]);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const getEmptyArray = (n) => Array.from({ length: n }, () => "");
|
|
44
|
+
if (grid.data[0].length === 0) {
|
|
45
|
+
grid.data[0] = [""];
|
|
46
|
+
}
|
|
47
|
+
// replace empty rows
|
|
48
|
+
grid.data.forEach((row, index) => {
|
|
49
|
+
if (row.length === 0) {
|
|
50
|
+
grid.data[index] = getEmptyArray(grid.data[0].length);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (grid.config.promoteHeaders && grid.data.length === 1) {
|
|
54
|
+
// table in Excel should have at least 2 rows
|
|
55
|
+
grid.data.push(getEmptyArray(grid.data[0].length));
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/*
|
|
59
|
+
* Validates the grid, throws an error if the grid is invalid.
|
|
60
|
+
* A valid grid has:
|
|
61
|
+
* - MxN structure.
|
|
62
|
+
* - If promoteHeaders is true - has at least 1 row, and in case adjustColumnNames is false, first row is unique and non empty.
|
|
63
|
+
*/
|
|
64
|
+
const validateGrid = (grid) => {
|
|
65
|
+
validateDataArrayDimensions(grid.data);
|
|
66
|
+
if (grid.config.promoteHeaders && grid.config.adjustColumnNames === false && !validateUniqueAndValidDataArray(grid.data[0])) {
|
|
67
|
+
throw new Error(constants_1.promotedHeadersCannotBeUsedWithoutAdjustingColumnNamesErr);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const validateDataArrayDimensions = (arr) => {
|
|
71
|
+
if (arr.length === 0 || arr[0].length === 0) {
|
|
72
|
+
throw new Error(constants_1.unexpectedErr);
|
|
73
|
+
}
|
|
74
|
+
if (!arr.every((innerArr) => innerArr.length === arr[0].length)) {
|
|
75
|
+
throw new Error(constants_1.arrayIsntMxNErr);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const validateUniqueAndValidDataArray = (arr) => {
|
|
79
|
+
if (arr.some((element) => element === "")) {
|
|
80
|
+
return false; // Array contains empty elements
|
|
81
|
+
}
|
|
82
|
+
const uniqueSet = new Set(arr);
|
|
83
|
+
return uniqueSet.size === arr.length;
|
|
84
|
+
};
|
|
85
|
+
const getAdjustedColumnNames = (columnNames) => {
|
|
86
|
+
if (columnNames === undefined) {
|
|
87
|
+
throw new Error(constants_1.unexpectedErr);
|
|
88
|
+
}
|
|
89
|
+
let i = 1;
|
|
90
|
+
// replace empty column names with default names, can still conflict if columns exist, but we handle that later
|
|
91
|
+
columnNames = columnNames.map((columnName) => columnName || `${constants_1.defaults.columnName} ${i++}`);
|
|
92
|
+
const uniqueNames = new Set();
|
|
93
|
+
return columnNames.map((name) => {
|
|
94
|
+
let uniqueName = name;
|
|
95
|
+
i = 1;
|
|
96
|
+
while (uniqueNames.has(uniqueName)) {
|
|
97
|
+
uniqueName = `${name} (${i++})`;
|
|
98
|
+
}
|
|
99
|
+
uniqueNames.add(uniqueName);
|
|
100
|
+
return uniqueName;
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
exports.default = { parseToTableData };
|
package/dist/utils/htmlUtils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT license.
|
|
2
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractTableValues = void 0;
|
|
4
5
|
const extractTableValues = (table) => {
|
|
5
|
-
const headers = [];
|
|
6
6
|
const rows = [];
|
|
7
7
|
// Extract values from each row
|
|
8
8
|
for (let i = 0; i < table.rows.length; i++) {
|
|
@@ -16,4 +16,4 @@ const extractTableValues = (table) => {
|
|
|
16
16
|
}
|
|
17
17
|
return rows;
|
|
18
18
|
};
|
|
19
|
-
exports.
|
|
19
|
+
exports.default = { extractTableValues };
|
package/dist/utils/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
6
|
};
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.tableUtils = exports.xmlInnerPartsUtils = exports.xmlPartsUtils = exports.documentUtils = exports.arrayUtils = exports.pqUtils = void 0;
|
|
8
|
+
exports.gridUtils = exports.htmlUtils = exports.tableUtils = exports.xmlInnerPartsUtils = exports.xmlPartsUtils = exports.documentUtils = exports.arrayUtils = exports.pqUtils = void 0;
|
|
9
9
|
var pqUtils_1 = require("./pqUtils");
|
|
10
10
|
Object.defineProperty(exports, "pqUtils", { enumerable: true, get: function () { return __importDefault(pqUtils_1).default; } });
|
|
11
11
|
var arrayUtils_1 = require("./arrayUtils");
|
|
@@ -18,3 +18,7 @@ var xmlInnerPartsUtils_1 = require("./xmlInnerPartsUtils");
|
|
|
18
18
|
Object.defineProperty(exports, "xmlInnerPartsUtils", { enumerable: true, get: function () { return __importDefault(xmlInnerPartsUtils_1).default; } });
|
|
19
19
|
var tableUtils_1 = require("./tableUtils");
|
|
20
20
|
Object.defineProperty(exports, "tableUtils", { enumerable: true, get: function () { return __importDefault(tableUtils_1).default; } });
|
|
21
|
+
var htmlUtils_1 = require("./htmlUtils");
|
|
22
|
+
Object.defineProperty(exports, "htmlUtils", { enumerable: true, get: function () { return __importDefault(htmlUtils_1).default; } });
|
|
23
|
+
var gridUtils_1 = require("./gridUtils");
|
|
24
|
+
Object.defineProperty(exports, "gridUtils", { enumerable: true, get: function () { return __importDefault(gridUtils_1).default; } });
|
|
@@ -37,17 +37,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.replaceSingleQuery = void 0;
|
|
40
|
+
exports.editSingleQueryMetadata = exports.getPackageComponents = exports.replaceSingleQuery = void 0;
|
|
41
41
|
const base64 = __importStar(require("base64-js"));
|
|
42
42
|
const jszip_1 = __importDefault(require("jszip"));
|
|
43
43
|
const constants_1 = require("./constants");
|
|
44
44
|
const _1 = require(".");
|
|
45
45
|
const replaceSingleQuery = (base64Str, queryName, queryMashupDoc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
|
-
const { version, packageOPC, permissionsSize, permissions, metadata, endBuffer } = getPackageComponents(base64Str);
|
|
46
|
+
const { version, packageOPC, permissionsSize, permissions, metadata, endBuffer } = (0, exports.getPackageComponents)(base64Str);
|
|
47
47
|
const newPackageBuffer = yield editSingleQueryPackage(packageOPC, queryMashupDoc);
|
|
48
48
|
const packageSizeBuffer = _1.arrayUtils.getInt32Buffer(newPackageBuffer.byteLength);
|
|
49
49
|
const permissionsSizeBuffer = _1.arrayUtils.getInt32Buffer(permissionsSize);
|
|
50
|
-
const newMetadataBuffer = editSingleQueryMetadata(metadata, { queryName });
|
|
50
|
+
const newMetadataBuffer = (0, exports.editSingleQueryMetadata)(metadata, { queryName });
|
|
51
51
|
const metadataSizeBuffer = _1.arrayUtils.getInt32Buffer(newMetadataBuffer.byteLength);
|
|
52
52
|
const newMashup = _1.arrayUtils.concatArrays(version, packageSizeBuffer, newPackageBuffer, permissionsSizeBuffer, permissions, metadataSizeBuffer, newMetadataBuffer, endBuffer);
|
|
53
53
|
return base64.fromByteArray(newMashup);
|
|
@@ -73,6 +73,7 @@ const getPackageComponents = (base64Str) => {
|
|
|
73
73
|
endBuffer,
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
|
+
exports.getPackageComponents = getPackageComponents;
|
|
76
77
|
const editSingleQueryPackage = (packageOPC, queryMashupDoc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
78
|
const packageZip = yield jszip_1.default.loadAsync(packageOPC);
|
|
78
79
|
setSection1m(queryMashupDoc, packageZip);
|
|
@@ -89,7 +90,6 @@ const setSection1m = (queryMashupDoc, zip) => {
|
|
|
89
90
|
});
|
|
90
91
|
};
|
|
91
92
|
const editSingleQueryMetadata = (metadataArray, metadata) => {
|
|
92
|
-
var _a;
|
|
93
93
|
//extract metadataXml
|
|
94
94
|
const mashupArray = new _1.arrayUtils.ArrayReader(metadataArray.buffer);
|
|
95
95
|
const metadataVersion = mashupArray.getBytes(4);
|
|
@@ -110,7 +110,7 @@ const editSingleQueryMetadata = (metadataArray, metadata) => {
|
|
|
110
110
|
const content = itemPath.innerHTML;
|
|
111
111
|
if (content.includes(constants_1.section1PathPrefix)) {
|
|
112
112
|
const strArr = content.split(constants_1.divider);
|
|
113
|
-
strArr[1] = metadata.queryName;
|
|
113
|
+
strArr[1] = encodeURIComponent(metadata.queryName);
|
|
114
114
|
const newContent = strArr.join(constants_1.divider);
|
|
115
115
|
itemPath.textContent = newContent;
|
|
116
116
|
}
|
|
@@ -125,28 +125,9 @@ const editSingleQueryMetadata = (metadataArray, metadata) => {
|
|
|
125
125
|
const entryProp = entryAttributesArr.find((prop) => {
|
|
126
126
|
return (prop === null || prop === void 0 ? void 0 : prop.name) === constants_1.elementAttributes.type;
|
|
127
127
|
});
|
|
128
|
-
if ((entryProp === null || entryProp === void 0 ? void 0 : entryProp.nodeValue) == constants_1.elementAttributes.relationshipInfo) {
|
|
129
|
-
const newValue = (_a = entry
|
|
130
|
-
.getAttribute(constants_1.elementAttributes.value)) === null || _a === void 0 ? void 0 : _a.replace(/Query1/g, metadata.queryName);
|
|
131
|
-
if (newValue) {
|
|
132
|
-
entry.setAttribute(constants_1.elementAttributes.value, newValue);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
128
|
if ((entryProp === null || entryProp === void 0 ? void 0 : entryProp.nodeValue) == constants_1.elementAttributes.resultType) {
|
|
136
129
|
entry.setAttribute(constants_1.elementAttributes.value, constants_1.elementAttributesValues.tableResultType());
|
|
137
130
|
}
|
|
138
|
-
if ((entryProp === null || entryProp === void 0 ? void 0 : entryProp.nodeValue) == constants_1.elementAttributes.fillColumnNames) {
|
|
139
|
-
const oldValue = entry.getAttribute(constants_1.elementAttributes.value);
|
|
140
|
-
if (oldValue) {
|
|
141
|
-
entry.setAttribute(constants_1.elementAttributes.value, oldValue.replace(constants_1.defaults.queryName, metadata.queryName));
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
if ((entryProp === null || entryProp === void 0 ? void 0 : entryProp.nodeValue) == constants_1.elementAttributes.fillTarget) {
|
|
145
|
-
const oldValue = entry.getAttribute(constants_1.elementAttributes.value);
|
|
146
|
-
if (oldValue) {
|
|
147
|
-
entry.setAttribute(constants_1.elementAttributes.value, oldValue.replace(constants_1.defaults.queryName, metadata.queryName));
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
131
|
if ((entryProp === null || entryProp === void 0 ? void 0 : entryProp.nodeValue) == constants_1.elementAttributes.fillLastUpdated) {
|
|
151
132
|
const nowTime = new Date().toISOString();
|
|
152
133
|
entry.setAttribute(constants_1.elementAttributes.value, (constants_1.elementAttributes.day + nowTime).replace(/Z/, "0000Z"));
|
|
@@ -161,3 +142,4 @@ const editSingleQueryMetadata = (metadataArray, metadata) => {
|
|
|
161
142
|
const newMetadataArray = _1.arrayUtils.concatArrays(metadataVersion, newMetadataXmlSize, newMetadataXml, endBuffer);
|
|
162
143
|
return newMetadataArray;
|
|
163
144
|
};
|
|
145
|
+
exports.editSingleQueryMetadata = editSingleQueryMetadata;
|
package/dist/utils/pqUtils.js
CHANGED
|
@@ -13,13 +13,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
const constants_1 = require("./constants");
|
|
15
15
|
const generators_1 = require("../generators");
|
|
16
|
+
const buffer_1 = require("buffer");
|
|
16
17
|
const getBase64 = (zip) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
18
|
const mashup = yield getDataMashupFile(zip);
|
|
18
19
|
return mashup.value;
|
|
19
20
|
});
|
|
20
21
|
const setBase64 = (zip, base64) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
22
|
const newXml = (0, generators_1.generateMashupXMLTemplate)(base64);
|
|
22
|
-
const encoded = Buffer.from(constants_1.BOM + newXml,
|
|
23
|
+
const encoded = buffer_1.Buffer.from(constants_1.BOM + newXml, "ucs2");
|
|
23
24
|
const mashup = yield getDataMashupFile(zip);
|
|
24
25
|
zip.file(mashup === null || mashup === void 0 ? void 0 : mashup.path, encoded);
|
|
25
26
|
});
|
|
@@ -37,7 +38,7 @@ const getDataMashupFile = (zip) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
37
38
|
}
|
|
38
39
|
return mashup;
|
|
39
40
|
});
|
|
40
|
-
const getCustomXmlFile = (zip, url, encoding =
|
|
41
|
+
const getCustomXmlFile = (zip, url, encoding = "utf16le") => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
42
|
var _a, _b;
|
|
42
43
|
const parser = new DOMParser();
|
|
43
44
|
const itemsArray = yield zip.file(/customXml\/item\d.xml/);
|
|
@@ -54,7 +55,9 @@ const getCustomXmlFile = (zip, url, encoding = 'utf16le') => __awaiter(void 0, v
|
|
|
54
55
|
if (xmlValue === undefined) {
|
|
55
56
|
break;
|
|
56
57
|
}
|
|
57
|
-
xmlString = Buffer.from(xmlValue)
|
|
58
|
+
xmlString = buffer_1.Buffer.from(xmlValue)
|
|
59
|
+
.toString(encoding)
|
|
60
|
+
.replace(/^\ufeff/, "");
|
|
58
61
|
const doc = parser.parseFromString(xmlString, "text/xml");
|
|
59
62
|
found = ((_b = doc === null || doc === void 0 ? void 0 : doc.documentElement) === null || _b === void 0 ? void 0 : _b.namespaceURI) === url;
|
|
60
63
|
if (found) {
|
|
@@ -81,7 +84,7 @@ const validateQueryName = (queryName) => {
|
|
|
81
84
|
throw new Error(constants_1.QueryNameMaxLengthErr);
|
|
82
85
|
}
|
|
83
86
|
if (queryNameHasInvalidChars(queryName)) {
|
|
84
|
-
throw new Error(constants_1.
|
|
87
|
+
throw new Error(constants_1.QueryNameInvalidCharsErr);
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
if (!queryName.trim()) {
|
package/dist/utils/tableUtils.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT license.
|
|
2
4
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
5
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
6
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -24,7 +26,7 @@ const updateTableInitialDataIfNeeded = (zip, tableData, updateQueryTable) => __a
|
|
|
24
26
|
if (sheetsXmlString === undefined) {
|
|
25
27
|
throw new Error(constants_1.sheetsNotFoundErr);
|
|
26
28
|
}
|
|
27
|
-
const newSheet =
|
|
29
|
+
const newSheet = updateSheetsInitialData(sheetsXmlString, tableData);
|
|
28
30
|
zip.file(constants_1.sheetsXmlPath, newSheet);
|
|
29
31
|
if (updateQueryTable) {
|
|
30
32
|
const queryTableXmlString = yield ((_b = zip.file(constants_1.queryTableXmlPath)) === null || _b === void 0 ? void 0 : _b.async(constants_1.textResultType));
|
|
@@ -38,17 +40,17 @@ const updateTableInitialDataIfNeeded = (zip, tableData, updateQueryTable) => __a
|
|
|
38
40
|
if (workbookXmlString === undefined) {
|
|
39
41
|
throw new Error(constants_1.sheetsNotFoundErr);
|
|
40
42
|
}
|
|
41
|
-
const newWorkbook =
|
|
43
|
+
const newWorkbook = updateWorkbookInitialData(workbookXmlString, tableData);
|
|
42
44
|
zip.file(constants_1.workbookXmlPath, newWorkbook);
|
|
43
45
|
}
|
|
44
46
|
const tableXmlString = yield ((_d = zip.file(constants_1.tableXmlPath)) === null || _d === void 0 ? void 0 : _d.async(constants_1.textResultType));
|
|
45
47
|
if (tableXmlString === undefined) {
|
|
46
48
|
throw new Error(constants_1.tableNotFoundErr);
|
|
47
49
|
}
|
|
48
|
-
const newTable =
|
|
50
|
+
const newTable = updateTablesInitialData(tableXmlString, tableData, updateQueryTable);
|
|
49
51
|
zip.file(constants_1.tableXmlPath, newTable);
|
|
50
52
|
});
|
|
51
|
-
const updateTablesInitialData = (tableXmlString, tableData, updateQueryTable = false) =>
|
|
53
|
+
const updateTablesInitialData = (tableXmlString, tableData, updateQueryTable = false) => {
|
|
52
54
|
const parser = new DOMParser();
|
|
53
55
|
const serializer = new XMLSerializer();
|
|
54
56
|
const tableDoc = parser.parseFromString(tableXmlString, constants_1.xmlTextResultType);
|
|
@@ -73,18 +75,17 @@ const updateTablesInitialData = (tableXmlString, tableData, updateQueryTable = f
|
|
|
73
75
|
.getElementsByTagName(constants_1.element.autoFilter)[0]
|
|
74
76
|
.setAttribute(constants_1.elementAttributes.reference, `A1:${documentUtils_1.default.getCellReferenceRelative(tableData.columnNames.length - 1, tableData.rows.length + 1)}`);
|
|
75
77
|
return serializer.serializeToString(tableDoc);
|
|
76
|
-
}
|
|
77
|
-
const updateWorkbookInitialData = (workbookXmlString, tableData) =>
|
|
78
|
+
};
|
|
79
|
+
const updateWorkbookInitialData = (workbookXmlString, tableData) => {
|
|
78
80
|
const newParser = new DOMParser();
|
|
79
81
|
const newSerializer = new XMLSerializer();
|
|
80
82
|
const workbookDoc = newParser.parseFromString(workbookXmlString, constants_1.xmlTextResultType);
|
|
81
83
|
const definedName = workbookDoc.getElementsByTagName(constants_1.element.definedName)[0];
|
|
82
84
|
definedName.textContent =
|
|
83
|
-
constants_1.defaults.sheetName +
|
|
84
|
-
`!$A$1:${documentUtils_1.default.getCellReferenceAbsolute(tableData.columnNames.length - 1, tableData.rows.length + 1)}`;
|
|
85
|
+
constants_1.defaults.sheetName + `!$A$1:${documentUtils_1.default.getCellReferenceAbsolute(tableData.columnNames.length - 1, tableData.rows.length + 1)}`;
|
|
85
86
|
return newSerializer.serializeToString(workbookDoc);
|
|
86
|
-
}
|
|
87
|
-
const updateQueryTablesInitialData = (queryTableXmlString, tableData) =>
|
|
87
|
+
};
|
|
88
|
+
const updateQueryTablesInitialData = (queryTableXmlString, tableData) => {
|
|
88
89
|
const parser = new DOMParser();
|
|
89
90
|
const serializer = new XMLSerializer();
|
|
90
91
|
const queryTableDoc = parser.parseFromString(queryTableXmlString, constants_1.xmlTextResultType);
|
|
@@ -98,12 +99,10 @@ const updateQueryTablesInitialData = (queryTableXmlString, tableData) => __await
|
|
|
98
99
|
queryTableFields.appendChild(queryTableField);
|
|
99
100
|
});
|
|
100
101
|
queryTableFields.setAttribute(constants_1.elementAttributes.count, tableData.columnNames.length.toString());
|
|
101
|
-
queryTableDoc
|
|
102
|
-
.getElementsByTagName(constants_1.element.queryTableRefresh)[0]
|
|
103
|
-
.setAttribute(constants_1.elementAttributes.nextId, (tableData.columnNames.length + 1).toString());
|
|
102
|
+
queryTableDoc.getElementsByTagName(constants_1.element.queryTableRefresh)[0].setAttribute(constants_1.elementAttributes.nextId, (tableData.columnNames.length + 1).toString());
|
|
104
103
|
return serializer.serializeToString(queryTableDoc);
|
|
105
|
-
}
|
|
106
|
-
const updateSheetsInitialData = (sheetsXmlString, tableData) =>
|
|
104
|
+
};
|
|
105
|
+
const updateSheetsInitialData = (sheetsXmlString, tableData) => {
|
|
107
106
|
const parser = new DOMParser();
|
|
108
107
|
const serializer = new XMLSerializer();
|
|
109
108
|
const sheetsDoc = parser.parseFromString(sheetsXmlString, constants_1.xmlTextResultType);
|
|
@@ -130,11 +129,11 @@ const updateSheetsInitialData = (sheetsXmlString, tableData) => __awaiter(void 0
|
|
|
130
129
|
sheetData.appendChild(newRow);
|
|
131
130
|
rowIndex++;
|
|
132
131
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
const reference = documentUtils_1.default.getTableReference(tableData.rows[0].length - 1, tableData.rows.length + 1);
|
|
133
|
+
sheetsDoc.getElementsByTagName(constants_1.element.dimension)[0].setAttribute(constants_1.elementAttributes.reference, reference);
|
|
134
|
+
sheetsDoc.getElementsByTagName(constants_1.element.selection)[0].setAttribute(constants_1.elementAttributes.sqref, reference);
|
|
136
135
|
return serializer.serializeToString(sheetsDoc);
|
|
137
|
-
}
|
|
136
|
+
};
|
|
138
137
|
exports.default = {
|
|
139
138
|
updateTableInitialDataIfNeeded,
|
|
140
139
|
updateSheetsInitialData,
|