Книга Exсel – это ZIP архив с каталогами и файлами XML в формате Open XML. Парсить XML отлично умеет jQuery, а вот зиппить нет. Для этого на просторах сети была найдена библиотека zip.js, которая прекрасно справилась с поставленной задачей.
Итак, попробуем посмотреть, что же находится внутри архива:
<div class="main"> <progress id="progress"></progress> <div class="filedrag" id="comps">Перетащите файл <span class="red">сюда</span></div> <div class="result"></div> </div>
var c = document.getElementById("comps"), FileDragHover = function (e) { e.stopPropagation(); e.preventDefault(); if(e.target.id==='comps') e.target.className = (e.type == "dragover" ? "filedrag hover" : "filedrag"); else c.className = (e.type == "dragover" ? "filedrag hover" : "filedrag"); } c.addEventListener("drop", function(e){ e.preventDefault(); c.className = "filedrag"; var files = e.target.files || e.dataTransfer.files; for (var i = 0, f; f = files[i]; i++) { if(f.name.toLowerCase().indexOf('xlsx')<=0) { alert('Это не файл Excel'); } else { zip.createReader(new zip.BlobReader(f), function(reader) { // Получаем все файлы архива reader.getEntries(function(entries) { // В консоли появятся все внутренности архива Excel console.info(entries) return false; }); }, function(error) { alert("Ошибка: " + error) }); } } return false; }, false); c.addEventListener("dragover", FileDragHover, false); c.addEventListener("dragleave", FileDragHover, false);
Результат можно посмотреть тут. Скачайте пример файла и перетащите его на форму.
В консоли появится список всех файлов архива книги Excel. Среди свойств объектов, появившихся в консоли, есть filename, по нему-то мы и будем искать необходимые нам файлы XML.
Нам понадобятся два файла из архива:
- import.xlsx\xl\worksheets\sheet[N].xlsx
- import.xlsx\xl\sharedStrings.xml
где:
sheet[N].xlsx — собственно лист Excel, N — его внутренний номер в книге.
sharedStrings.xml — ассоциативный массив строк, словарь листа.
Отфильтруем только нужные для нас файлы:
// Получаем все файлы архива reader.getEntries(function(entries) { var a=[],st; for(var i in entries){ var e=entries[i]; var fn=e.filename.toLowerCase(); if(fn.indexOf("sheet")>0){ a.push(e); } else if(fn.indexOf("sharedstring")>0){ st=e; } } // Массив всех листов книги Excel console.info(a) // Ассоциативный массив строк console.info(st) return false; });
Результат можно посмотреть тут, закинув файл и посмотрев в консоль.
Далее нам необходимо извлечь данные простыми селекторами, для словаря строк это — st t, для записей таблицы с данными на листе это — sheetdata row.
Добавим функцию для вывода данных из листа Excel:
printExcelData = function(sheets, strings) { var unzipProgress = document.getElementById("progress"); unzipProgress.style.display='block'; strings.getData(new zip.TextWriter(), function(text) { // Получаем все строки листа для ассоциации с их кодами var i,st=$($.parseXML(decodeURIComponent(escape(text)))).find('si t'); for(i=0;i<st.length;++i) st[i]=$(st[i]).text(); // Перебираем листы в поисках нужного var parseSheet=function(sheet){ var j,i,h,sh,d=[],s; sheet.getData(new zip.TextWriter(), function(text) { // а вот и наши записи sh=$($.parseXML(decodeURIComponent(escape(text)))).find('sheetdata row'); // делаем из строки объект sh.each(function(e){ var c=$(this).find('c'),ci,v,o={}; for(i=0;i<c.length;++i){ ci=$(c[i]); v=ci.find('v').text(); if(ci.attr('t')) v=st[v]; j=ci.attr('r').charCodeAt(0)-65; if(h) o[h[j]]=v; else o[j]=v; } if(h){ d.push(o) } else h=o; }); var id_name=""; for(i in h) if(h[i]=='Comp_Id'){ id_name=h[i]; break; } // Если поле Comp_Id есть в записи, значит лист наш if(id_name=='Comp_Id') { unzipProgress.style.display='none'; // Это заголовок таблицы данных s=""; for(i=0;i<Object.keys(h).length;i++) s+='<th>'+h[i]+'</th>'; $('.result thead tr').append(s) // Это данные s=""; for(j=0; j<d.length; j++){ s+='<tr>'; for(i=0; i<Object.keys(h).length; i++){ s+='<td>'+d[j][h[i]].toString()+'</td>'; } s+='</tr>'; } $('.result tbody').append(s) sheets=[]; return; } if(sheets.length>0) parseSheet(sheets.pop()); }, function(current, total) { unzipProgress.value = current; unzipProgress.max = total; }); } parseSheet(sheets.pop()); }, function(current, total) { unzipProgress.value = current; unzipProgress.max = total; }); }
ссылка на оригинал статьи http://habrahabr.ru/post/200770/
Добавить комментарий