Skip to content

Instantly share code, notes, and snippets.

@pl4nty
Last active June 19, 2020 14:31
Show Gist options
  • Save pl4nty/adb9c782092d27e81a3785d3ce0ab180 to your computer and use it in GitHub Desktop.
Save pl4nty/adb9c782092d27e81a3785d3ce0ab180 to your computer and use it in GitHub Desktop.
Proof that downloads are blocked in modern Excel add-ins. Written while developing Excel2LaTeX.
name: Excel Add-in Download Blocked PoC
description: Proof that downloads are blocked in modern Excel add-ins. Written while developing Excel2LaTeX.
host: EXCEL
api_set: {}
script:
content: >
document.getElementById("test").addEventListener("click", function(event) {
console.log(File);
var blob = new Blob(["foo"], {
type: "text/plain"
});
let url = window.URL.createObjectURL(blob);
url = url.slice(5);
console.log(url);
var a = document.getElementById("test2");
a.href = url;
run();
});
document.getElementById("test2").addEventListener("click", function (event)
{
let url = document.getElementById("test2").href;
console.log(url);
URL.revokeObjectURL(url);
});
function run() {
Excel.run(async (context) => {
const range = context.workbook.getSelectedRange();
range.load(["values"]);
const cellProps = range.getCellProperties({
address: true,
format: {
fill: {
color: true
},
font: {
color: true
}
},
style: true
});
await context.sync();
return toLatex(range.values.map((row, i) => row.map((value, j) => [value, cellProps.value[i][j].format])));
}).then((text) => {
console.log(text);
const node = document.getElementById("container");
node.innerText = text;
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("copy");
});
}
/** Default helper for invoking an action and handling errors. */
async function tryCatch(callback) {
try {
await callback();
} catch (error) {
// Note: In a production add-in, you'd want to notify the user through your add-in's UI.
console.error(error);
}
}
function toLatex(range) {
console.log(range);
let packages = {
color: "",
strikethrough: "",
subscript: ""
};
let body = "\\begin{tabular}";
for (let row of range) {
for (let cell of row) {
cell[0] = cell[0].toString(); // cells can be strings, numbers or bools
if (cell[0] === "") cell[0] = " ";
let [p, text] = applyFormat(packages, cell);
packages = p;
body += `${text}`;
}
row = row.join(" & ") + "\\\\";
}
return Object.values(packages).join("") + body + "\\end{tabular}";
}
// Only applies if format applied to entire cell, not just letters
function applyFormat(packages, [value, format]) {
if (format.font.bold) value = `\\textbf{${value}}`;
if (format.font.color !== "#000000") {
if (!packages.color) packages.color = "\\usepackage{xcolor}\n";
value = `\\textcolor{${format.font.color}}{${value}}`;
}
if (format.font.italic) value = `\\textit{${value}}`;
// apply font?
// don't change font size
if (format.font.strikethrough) {
if (!packages.strikethrough) packages.strikethrough = "\\usepackage{cancel}\n";
value = `\\cancel{${value}}`;
}
if (format.font.subscript) {
if (!packages.subscript) packages.subscript = "\\usepackage{fixltx2e}\n";
value = `\\textsubscript{${value}}`;
}
if (format.font.superscript) value = `\\textsuperscript{${value}}`;
if (format.font.underline) value = `\\underline{${value}}`;
return [packages, value];
}
language: typescript
template:
content: "<section class=\"ms-font-m\">\n\t<p class=\"ms-font-m\">This sample demonstrates basic Excel API calls.</p>\n</section>\n\n<section class=\"samples ms-font-m\">\n\t<h3>Try it out</h3>\n\t<p class=\"ms-font-m\">Select some cells in the worksheet, then press <b>Highlight selected range</b>.</p>\n\t<button id=\"run\" class=\"ms-Button\">\n <span class=\"ms-Button-label\">Highlight selected range</span>\n </button>\n</section>\n\n<button id=\"test\">\n\tboop\n</button>\n\n<a id=\"test2\" href=\"https://www.google.com/robots.txt\" download>\n\tbeep\n</a>\n\n<p id=\"container\"></p>"
language: html
style:
content: |-
section.samples {
margin-top: 20px;
}
section.samples .ms-Button, section.setup .ms-Button {
display: block;
margin-bottom: 5px;
margin-left: 20px;
min-width: 80px;
}
language: css
libraries: |-
https://appsforoffice.microsoft.com/lib/1/hosted/office.js
@types/office-js
office-ui-fabric-js@1.4.0/dist/css/fabric.min.css
office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css
core-js@2.4.1/client/core.min.js
@types/core-js
jquery@3.1.1
@types/jquery@3.3.1
file-saver@2.0.2
@types/file-saver@2.0.2
@types/node
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment