Ability to select workbooks. Fixes #4
This commit is contained in:
parent
bd6fd498aa
commit
c5b4fa8f40
322
converter.js
322
converter.js
|
@ -1,151 +1,215 @@
|
||||||
excelParser = {
|
!(function($) {
|
||||||
latexEscape: function(text) {
|
"use strict";
|
||||||
escapeRegExpr = function(str) {
|
|
||||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
|
||||||
};
|
|
||||||
|
|
||||||
var specials = ['\\', '&', '%', '$', '#', '_', '{', '}', '~', '^'];
|
// Global variable with information on current workbooks. Don't judge me.
|
||||||
$.each(specials, function() {
|
var workbooks = {};
|
||||||
var regexp = new RegExp(escapeRegExpr(this), 'g');
|
|
||||||
text = text.replace(regexp, '\\' + this, 'g');
|
|
||||||
});
|
|
||||||
|
|
||||||
return text;
|
// Another global to store LaTeX output. Don't judge me...again...
|
||||||
},
|
var latexOutput = {};
|
||||||
|
|
||||||
parseStringTable: function(data) {
|
var excelParser = {
|
||||||
var doc = $(data);
|
latexEscape: function(text) {
|
||||||
var stringTags = doc.find('si');
|
var escapeRegExpr = function(str) {
|
||||||
var strings = $.map(stringTags, function(s,i) {
|
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||||
return $(s).find('t').text();
|
};
|
||||||
});
|
|
||||||
|
|
||||||
return strings;
|
var specials = ['\\', '&', '%', '$', '#', '_', '{', '}', '~', '^'];
|
||||||
},
|
$.each(specials, function() {
|
||||||
|
var regexp = new RegExp(escapeRegExpr(this), 'g');
|
||||||
|
text = text.replace(regexp, '\\' + this, 'g');
|
||||||
|
});
|
||||||
|
|
||||||
toLatex: function(table) {
|
return text;
|
||||||
var max = 0;
|
},
|
||||||
for(var i=0; i < table.length; i++) {
|
|
||||||
if(table[i] && table[i].length > max) { max = table[i].length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
var numCols = max;
|
parseStringTable: function(data) {
|
||||||
var args = [];
|
var doc = $(data);
|
||||||
for(var i=0; i < numCols; i++) {
|
var stringTags = doc.find('si');
|
||||||
args[i] = 'l';
|
var strings = $.map(stringTags, function(s,i) {
|
||||||
}
|
return $(s).find('t').text();
|
||||||
args = ' | ' + args.join(' | ') + ' | ';
|
});
|
||||||
var latex = "\\begin{tabular}{" + args + "}\n\\hline\n";
|
|
||||||
for(var i=0; i < table.length; i++) {
|
return strings;
|
||||||
var cols = table[i];
|
},
|
||||||
// TODO: replace "&" with "\&"
|
|
||||||
if(cols === undefined) { cols = []; }
|
toLatex: function(table) {
|
||||||
if(cols.length < numCols) {
|
var max = 0;
|
||||||
for(var x=cols.length; x < max; x++) {
|
for(var i=0; i < table.length; i++) {
|
||||||
cols[x] = '\\ ';
|
if(table[i] && table[i].length > max) { max = table[i].length; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
latex += "\t" + cols.join(' & ');
|
var numCols = max;
|
||||||
latex += " \\\\ \\hline\n";
|
var args = [];
|
||||||
}
|
for(i=0; i < numCols; i++) {
|
||||||
|
args[i] = 'l';
|
||||||
latex += "\\end{tabular}\n";
|
}
|
||||||
|
args = ' | ' + args.join(' | ') + ' | ';
|
||||||
$('#latex-output').val(latex);
|
var latex = "\\begin{tabular}{" + args + "}\n\\hline\n";
|
||||||
},
|
for(i=0; i < table.length; i++) {
|
||||||
|
var cols = table[i];
|
||||||
processSheet: function(data, stringTable) {
|
// TODO: replace "&" with "\&"
|
||||||
// get jQuery object out of the data for accessing stuffs
|
if(cols === undefined) { cols = []; }
|
||||||
var doc = $(data);
|
if(cols.length < numCols) {
|
||||||
|
for(var x=cols.length; x < max; x++) {
|
||||||
var table = [];
|
cols[x] = '\\ ';
|
||||||
|
}
|
||||||
var rows = doc.find('sheetdata row');
|
|
||||||
$.each(rows, function(i,row) {
|
|
||||||
var rowNum = parseInt($(row).attr('r'));
|
|
||||||
|
|
||||||
// get columns
|
|
||||||
var cols = $(row).find('c');
|
|
||||||
var colVals = $.map(cols, function(col,j) {
|
|
||||||
var col = $(col);
|
|
||||||
var val = excelParser.latexEscape(col.find('v').text());
|
|
||||||
if(col.attr('t') == 's') {
|
|
||||||
return excelParser.latexEscape(stringTable[parseInt(val)]);
|
|
||||||
} else {
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
latex += "\t" + cols.join(' & ');
|
||||||
|
latex += " \\\\ \\hline\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
latex += "\\end{tabular}\n";
|
||||||
|
|
||||||
|
return latex;
|
||||||
|
},
|
||||||
|
|
||||||
|
processSheet: function(data, stringTable) {
|
||||||
|
// get jQuery object out of the data for accessing stuffs
|
||||||
|
var doc = $(data);
|
||||||
|
|
||||||
|
var table = [];
|
||||||
|
|
||||||
|
var rows = doc.find('sheetdata row');
|
||||||
|
$.each(rows, function(i,row) {
|
||||||
|
var rowNum = parseInt($(row).attr('r'), 10);
|
||||||
|
|
||||||
|
// get columns
|
||||||
|
var cols = $(row).find('c');
|
||||||
|
var colVals = $.map(cols, function(col,j) {
|
||||||
|
col = $(col);
|
||||||
|
var val = excelParser.latexEscape(col.find('v').text());
|
||||||
|
if(col.attr('t') == 's') {
|
||||||
|
return excelParser.latexEscape(stringTable[parseInt(val, 10)]);
|
||||||
|
} else {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
table[rowNum-1] = colVals;
|
||||||
});
|
});
|
||||||
table[rowNum-1] = colVals;
|
|
||||||
});
|
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSheet: function(entries, stringTable) {
|
handleSheets: function(entries, stringTable) {
|
||||||
// filter out all files that aren't worksheets
|
// get the workbook.xml file, which contains the names of all workbooks
|
||||||
var sheets = $.grep(entries, function(n,i) {
|
var workbookMeta = entries.filter(function(entry) {
|
||||||
return (/^xl\/worksheets\/.*\.xml$/.test(n.filename)) && (!/^xl\/worksheets\/_rels/.test(n.filename));
|
return entry.filename === 'xl/workbook.xml';
|
||||||
});
|
})[0];
|
||||||
|
|
||||||
// for now, only process the first sheet
|
// filter out all files that aren't worksheets
|
||||||
// TODO: give the user a choice of which sheet to process
|
var sheets = $.grep(entries, function(n,i) {
|
||||||
var sheet = sheets[0];
|
var filter1 = /^xl\/worksheets\/.*\.xml$/;
|
||||||
sheet.getData(new zip.TextWriter(), function(text) {
|
var filter2 = /^xl\/worksheets\/_rels/;
|
||||||
var table = excelParser.processSheet(text, stringTable);
|
return (filter1.test(n.filename)) && (!filter2.test(n.filename));
|
||||||
excelParser.toLatex(table);
|
});
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
handleFile: function(event) {
|
// read the workbook meta data to get the names and crap
|
||||||
// prevent default browser behavior
|
workbookMeta.getData(new zip.TextWriter(), function(text) {
|
||||||
event.stopPropagation();
|
var doc = $(text);
|
||||||
event.preventDefault();
|
|
||||||
|
// extract the names of the workbooks and their IDs for use later on...
|
||||||
// get file information
|
$.each(doc.find('sheets sheet'), function(i, tag) {
|
||||||
var files = event.dataTransfer.files;
|
tag = $(tag);
|
||||||
if(!files.length) {
|
var id = tag.attr('sheetId');
|
||||||
// no files were given somehow...
|
var name = tag.attr('name');
|
||||||
$('#latex-output').val('No files were given...try again?');
|
workbooks[id] = name;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var blob = files[0];
|
|
||||||
|
|
||||||
// unzip and process files
|
|
||||||
zip.createReader(new zip.BlobReader(blob), function(reader) {
|
|
||||||
reader.getEntries(function(entries) {
|
|
||||||
if(!entries.length) { return false; }
|
|
||||||
|
|
||||||
// get the string table
|
|
||||||
var stFile = $.grep(entries, function(n,i) {
|
|
||||||
return /^xl\/sharedStrings\.xml$/.test(n.filename);
|
|
||||||
})[0];
|
|
||||||
|
|
||||||
stFile.getData(new zip.TextWriter(), function(text) {
|
|
||||||
var stringTable = excelParser.parseStringTable(text);
|
|
||||||
excelParser.handleSheet(entries, stringTable);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
excelParser.updateSelect();
|
||||||
|
|
||||||
|
// iterate over all sheets and convert them to LaTeX
|
||||||
|
$.each(sheets, function(_, sheet) {
|
||||||
|
// the ID of the spreadsheet can only be found in the filename apparently :P
|
||||||
|
var id = sheet.filename.match(/(\d)\.xml/)[1];
|
||||||
|
|
||||||
|
sheet.getData(new zip.TextWriter(), function(text) {
|
||||||
|
var table = excelParser.processSheet(text, stringTable);
|
||||||
|
var latex = excelParser.toLatex(table);
|
||||||
|
latexOutput[id] = latex;
|
||||||
|
|
||||||
|
// I apologize for the hack :(
|
||||||
|
if(id === '1') {
|
||||||
|
$('#latex-output').val(latex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
},
|
|
||||||
|
|
||||||
init: function() {
|
handleFiles: function(event) {
|
||||||
// hack because of jQuery shenanigans
|
// prevent default browser behavior
|
||||||
jQuery.event.props.push('dataTransfer');
|
|
||||||
|
|
||||||
$('body').bind('dragover', function(event) {
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.dataTransfer.dropEffect = 'copy';
|
|
||||||
});
|
|
||||||
|
|
||||||
$('body').bind('drop', excelParser.handleFile);
|
// get file information
|
||||||
}
|
var files = event.dataTransfer.files;
|
||||||
};
|
if(!files.length) {
|
||||||
|
// no files were given somehow...
|
||||||
|
$('#latex-output').val('No files were given...try again?');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$(function() {
|
var blob = files[0];
|
||||||
zip.workerScriptsPath = 'zip/';
|
|
||||||
excelParser.init();
|
// unzip and process files
|
||||||
});
|
zip.createReader(new zip.BlobReader(blob), function(reader) {
|
||||||
|
reader.getEntries(function(entries) {
|
||||||
|
if(!entries.length) { return false; }
|
||||||
|
|
||||||
|
// get the string table
|
||||||
|
var stFile = $.grep(entries, function(n,i) {
|
||||||
|
var regexp = /^xl\/sharedStrings\.xml$/;
|
||||||
|
return regexp.test(n.filename);
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
stFile.getData(new zip.TextWriter(), function(text) {
|
||||||
|
var stringTable = excelParser.parseStringTable(text);
|
||||||
|
excelParser.handleSheets(entries, stringTable);
|
||||||
|
});
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSelect: function() {
|
||||||
|
var select = $('#workbook');
|
||||||
|
|
||||||
|
// clear existing option tags
|
||||||
|
select.empty();
|
||||||
|
|
||||||
|
for(var id in workbooks) {
|
||||||
|
var tag = $('<option value="' + id + '">' + workbooks[id] + '</option>');
|
||||||
|
tag.appendTo(select);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
// hack because of jQuery shenanigans
|
||||||
|
jQuery.event.props.push('dataTransfer');
|
||||||
|
|
||||||
|
$('body').bind('dragover', function(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
event.dataTransfer.dropEffect = 'copy';
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').bind('drop', excelParser.handleFiles);
|
||||||
|
|
||||||
|
// when a new workbook is selected, do stuff!
|
||||||
|
$('#workbook').change(function(event) {
|
||||||
|
var select = $(event.target);
|
||||||
|
var output = latexOutput[select.val()];
|
||||||
|
$('#latex-output').val(output);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
zip.workerScriptsPath = 'zip/';
|
||||||
|
excelParser.init();
|
||||||
|
});
|
||||||
|
})(window.jQuery);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
<h1 class="title">excel => LaTeX</h1>
|
<h1 class="title">excel => LaTeX</h1>
|
||||||
<h4 class="info">Drag any .xlsx file onto the page to extract data and convert it into a LaTeX table</h4>
|
<h4 class="info">Drag any .xlsx file onto the page to extract data and convert it into a LaTeX table</h4>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
<label for="workbook">Workbook:</label>
|
||||||
|
<select id="workbook" name="workbook"></select>
|
||||||
|
|
||||||
<textarea id="latex-output" readonly="readonly"></textarea>
|
<textarea id="latex-output" readonly="readonly"></textarea>
|
||||||
<p>Mostly untested, so if you find a bug or have a feature request, <a href="https://github.com/eric-wood/excel2latex/issues">let me know!</a>
|
<p>Mostly untested, so if you find a bug or have a feature request, <a href="https://github.com/eric-wood/excel2latex/issues">let me know!</a>
|
||||||
<p class="disclaimer">Note: this only works with .xlsx files. That means .xls files will <b>not</b> work.</p>
|
<p class="disclaimer">Note: this only works with .xlsx files. That means .xls files will <b>not</b> work.</p>
|
||||||
|
@ -32,7 +35,7 @@
|
||||||
<p>Lovingly hacked together by <a href="http://ericwood.org">Eric Wood</a></p>
|
<p>Lovingly hacked together by <a href="http://ericwood.org">Eric Wood</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="zip/zip.js"></script>
|
<script type="text/javascript" src="zip/zip.js"></script>
|
||||||
<script type="text/javascript" src="converter.js"></script>
|
<script type="text/javascript" src="converter.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in New Issue