forked from sheetjs/sheetjs
XLSX write Sheet Protection
fixes #363 h/t @Mior note: @sheetjsdev rewrote implementation, original PR author used
This commit is contained in:
parent
6a3afe56c2
commit
d086dbecbf
22
README.md
22
README.md
@ -574,6 +574,28 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
will write all cells in the merge range if they exist, so be sure that only
|
will write all cells in the merge range if they exist, so be sure that only
|
||||||
the first cell (upper-left) in the range is set.
|
the first cell (upper-left) in the range is set.
|
||||||
|
|
||||||
|
- `ws['protect']`: object of write sheet protection properties. The `password`
|
||||||
|
key specifies the password. The writer uses the XOR obfuscation method. The
|
||||||
|
following keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
||||||
|
|
||||||
|
| key | functionality disabled if value is true |
|
||||||
|
|:----------------------|:-----------------------------------------------------|
|
||||||
|
| `selectLockedCells` | Select locked cells |
|
||||||
|
| `selectUnlockedCells` | Select unlocked cells |
|
||||||
|
| `formatCells` | Format cells |
|
||||||
|
| `formatColumns` | Format columns |
|
||||||
|
| `formatRows` | Format rows |
|
||||||
|
| `insertColumns` | Insert columns |
|
||||||
|
| `insertRows` | Insert rows |
|
||||||
|
| `insertHyperlinks` | Insert hyperlinks |
|
||||||
|
| `deleteColumns` | Delete columns |
|
||||||
|
| `deleteRows` | Delete rows |
|
||||||
|
| `sort` | Sort |
|
||||||
|
| `autoFilter` | Filter |
|
||||||
|
| `pivotTables` | Use PivotTable reports |
|
||||||
|
| `objects` | Edit objects |
|
||||||
|
| `scenarios` | Edit scenarios |
|
||||||
|
|
||||||
#### Chartsheet Object
|
#### Chartsheet Object
|
||||||
|
|
||||||
Chartsheets are represented as standard sheets. They are distinguished with the
|
Chartsheets are represented as standard sheets. They are distinguished with the
|
||||||
|
@ -70,6 +70,24 @@ function write_ws_xml_merges(merges) {
|
|||||||
return o + '</mergeCells>';
|
return o + '</mergeCells>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 18.3.1.85 sheetPr CT_SheetProtection */
|
||||||
|
function write_ws_xml_protection(sp)/*:string*/ {
|
||||||
|
// algorithmName, hashValue, saltValue, spinCountpassword
|
||||||
|
var o = ({sheet:1}/*:any*/);
|
||||||
|
var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
|
||||||
|
var deftrue = [
|
||||||
|
"formatColumns", "formatRows", "formatCells",
|
||||||
|
"insertColumns", "insertRows", "insertHyperlinks",
|
||||||
|
"deleteColumns", "deleteRows",
|
||||||
|
"sort", "autoFilter", "pivotTables"
|
||||||
|
];
|
||||||
|
deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
|
||||||
|
deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
|
||||||
|
/* TODO: algorithm */
|
||||||
|
if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
|
||||||
|
return writextag('sheetProtection', null, o);
|
||||||
|
}
|
||||||
|
|
||||||
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||||
for(var i = 0; i != data.length; ++i) {
|
for(var i = 0; i != data.length; ++i) {
|
||||||
var val = parsexmltag(data[i], true);
|
var val = parsexmltag(data[i], true);
|
||||||
@ -348,6 +366,8 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
|
|||||||
}
|
}
|
||||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||||
|
|
||||||
|
if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
|
||||||
|
|
||||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||||
|
|
||||||
var relc = -1, rel, rId = -1;
|
var relc = -1, rel, rId = -1;
|
||||||
|
@ -13,6 +13,28 @@ In addition to the base sheet keys, worksheets also add:
|
|||||||
will write all cells in the merge range if they exist, so be sure that only
|
will write all cells in the merge range if they exist, so be sure that only
|
||||||
the first cell (upper-left) in the range is set.
|
the first cell (upper-left) in the range is set.
|
||||||
|
|
||||||
|
- `ws['protect']`: object of write sheet protection properties. The `password`
|
||||||
|
key specifies the password. The writer uses the XOR obfuscation method. The
|
||||||
|
following keys control the sheet protection (same as ECMA-376 18.3.1.85):
|
||||||
|
|
||||||
|
| key | functionality disabled if value is true |
|
||||||
|
|:----------------------|:-----------------------------------------------------|
|
||||||
|
| `selectLockedCells` | Select locked cells |
|
||||||
|
| `selectUnlockedCells` | Select unlocked cells |
|
||||||
|
| `formatCells` | Format cells |
|
||||||
|
| `formatColumns` | Format columns |
|
||||||
|
| `formatRows` | Format rows |
|
||||||
|
| `insertColumns` | Insert columns |
|
||||||
|
| `insertRows` | Insert rows |
|
||||||
|
| `insertHyperlinks` | Insert hyperlinks |
|
||||||
|
| `deleteColumns` | Delete columns |
|
||||||
|
| `deleteRows` | Delete rows |
|
||||||
|
| `sort` | Sort |
|
||||||
|
| `autoFilter` | Filter |
|
||||||
|
| `pivotTables` | Use PivotTable reports |
|
||||||
|
| `objects` | Edit objects |
|
||||||
|
| `scenarios` | Edit scenarios |
|
||||||
|
|
||||||
#### Chartsheet Object
|
#### Chartsheet Object
|
||||||
|
|
||||||
Chartsheets are represented as standard sheets. They are distinguished with the
|
Chartsheets are represented as standard sheets. They are distinguished with the
|
||||||
|
@ -102,6 +102,13 @@ wb.Props = {
|
|||||||
ws['A4'].c = [];
|
ws['A4'].c = [];
|
||||||
ws['A4'].c.push({a:"SheetJS",t:"I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word"});
|
ws['A4'].c.push({a:"SheetJS",t:"I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word"});
|
||||||
|
|
||||||
|
/* TEST: sheet protection */
|
||||||
|
ws['!protect'] = {
|
||||||
|
password:"password",
|
||||||
|
objects:1,
|
||||||
|
scenarios:1
|
||||||
|
};
|
||||||
|
|
||||||
console.log("Worksheet Model:")
|
console.log("Worksheet Model:")
|
||||||
console.log(ws);
|
console.log(ws);
|
||||||
|
|
||||||
|
20
xlsx.flow.js
20
xlsx.flow.js
@ -9715,6 +9715,24 @@ function write_ws_xml_merges(merges) {
|
|||||||
return o + '</mergeCells>';
|
return o + '</mergeCells>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 18.3.1.85 sheetPr CT_SheetProtection */
|
||||||
|
function write_ws_xml_protection(sp)/*:string*/ {
|
||||||
|
// algorithmName, hashValue, saltValue, spinCountpassword
|
||||||
|
var o = ({sheet:1}/*:any*/);
|
||||||
|
var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
|
||||||
|
var deftrue = [
|
||||||
|
"formatColumns", "formatRows", "formatCells",
|
||||||
|
"insertColumns", "insertRows", "insertHyperlinks",
|
||||||
|
"deleteColumns", "deleteRows",
|
||||||
|
"sort", "autoFilter", "pivotTables"
|
||||||
|
];
|
||||||
|
deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
|
||||||
|
deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
|
||||||
|
/* TODO: algorithm */
|
||||||
|
if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
|
||||||
|
return writextag('sheetProtection', null, o);
|
||||||
|
}
|
||||||
|
|
||||||
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
function parse_ws_xml_hlinks(s, data/*:Array<string>*/, rels) {
|
||||||
for(var i = 0; i != data.length; ++i) {
|
for(var i = 0; i != data.length; ++i) {
|
||||||
var val = parsexmltag(data[i], true);
|
var val = parsexmltag(data[i], true);
|
||||||
@ -9993,6 +10011,8 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
|
|||||||
}
|
}
|
||||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||||
|
|
||||||
|
if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
|
||||||
|
|
||||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||||
|
|
||||||
var relc = -1, rel, rId = -1;
|
var relc = -1, rel, rId = -1;
|
||||||
|
20
xlsx.js
20
xlsx.js
@ -9658,6 +9658,24 @@ function write_ws_xml_merges(merges) {
|
|||||||
return o + '</mergeCells>';
|
return o + '</mergeCells>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 18.3.1.85 sheetPr CT_SheetProtection */
|
||||||
|
function write_ws_xml_protection(sp) {
|
||||||
|
// algorithmName, hashValue, saltValue, spinCountpassword
|
||||||
|
var o = ({sheet:1});
|
||||||
|
var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
|
||||||
|
var deftrue = [
|
||||||
|
"formatColumns", "formatRows", "formatCells",
|
||||||
|
"insertColumns", "insertRows", "insertHyperlinks",
|
||||||
|
"deleteColumns", "deleteRows",
|
||||||
|
"sort", "autoFilter", "pivotTables"
|
||||||
|
];
|
||||||
|
deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
|
||||||
|
deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
|
||||||
|
/* TODO: algorithm */
|
||||||
|
if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
|
||||||
|
return writextag('sheetProtection', null, o);
|
||||||
|
}
|
||||||
|
|
||||||
function parse_ws_xml_hlinks(s, data, rels) {
|
function parse_ws_xml_hlinks(s, data, rels) {
|
||||||
for(var i = 0; i != data.length; ++i) {
|
for(var i = 0; i != data.length; ++i) {
|
||||||
var val = parsexmltag(data[i], true);
|
var val = parsexmltag(data[i], true);
|
||||||
@ -9936,6 +9954,8 @@ function write_ws_xml(idx, opts, wb, rels) {
|
|||||||
}
|
}
|
||||||
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
|
||||||
|
|
||||||
|
if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
|
||||||
|
|
||||||
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
|
||||||
|
|
||||||
var relc = -1, rel, rId = -1;
|
var relc = -1, rel, rId = -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user