Введение


Всем привет! Сегодня я опишу довольно тривиальную, но нигде не освещенную тему экспорта из страницы данных в Excel. На мое удивление сам процесс не описан нигде в полной мере. Итак, приступим.

Все написано до нас


Подумал я и начал искать, нашел очень быстро SheetJS , но, боже мой, как там запущено все! Если с форматированием еще можно справиться, то стили — это головная боль.

Все написано до нас. Подход 2


В старом-старом SharePoint 2007 есть такая возможность экспортировать эксель файл, на удивление это работает до сих пор и хорошо поддается описанию.

Что нужно:

  • Современный браузер (проверьте в старых)
  • Отформатированная таблица
  • Colspan, rowspan, border — знание табличной верстки

var tableToExcel = (function() {
		var uri = 'data:application/vnd.ms-excel;base64,'
		, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body><table>{table}</table></body></html>'
		, base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
		, format = function(s, c) { 	    	 
			return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) 
		}
		, downloadURI = function(uri, name) {
		    var link = document.createElement("a");
		    link.download = name;
		    link.href = uri;
		    link.click();
		}

		return function(table, name, fileName) {
			if (!table.nodeType) table = document.getElementById(table)
				var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}
			var resuri = uri + base64(format(template, ctx))
			downloadURI(resuri, fileName);
		}
	})();  


    // params: element id, sheet name, file name
    tableToExcel('resultTable','Смета', 'Ремрайон_смета.xls');

Форматирование


Оформите саму сетку в таблице с помощью атрибутов colspan, rowspan, добавьте стили и после этого вызывайте генерацию файла.

В заключение


Могу ответить в комментах на ваши вопросы.

Комментарии (29)


  1. staticlab
    21.04.2018 21:49

    Сегодня я опишу довольно тривиальную, но ни где не освященную тему экспорт из страницы данных в Excel.

    Вы глубоко заблуждаетесь.


    SheetJS, но боже мой как там запущено все. Если с форматированием еще можно справится, то стили — это головная боль.

    Потому что целью является сконструировать настоящий XLS.


    Оформите саму сетку в таблице с помощью атрибутов colspan, rowspan, добавьте стили и после этого вызывайте генерацию файла.

    И в результате получим несовместимый с альтернативными программами документ. В LibreOffice, если повезёт, хотя бы сетка ячеек сохранится. В Numbers документ откроется, но без контента. А ещё есть всякие мобильные офисы, в том числе GDrive Viewer. Вам-то может быть всё равно, а клиенты будут жутко недовольны.


    1. firedragon
      21.04.2018 23:47

      20+ не работающих форков меня не впечатлили. Впрочем тема xls благостна для холиваров.


  1. urrri
    21.04.2018 22:00
    +1

    Сегодня я опишу довольно тривиальную, но ни где не освященную тему

    <humor>Освящать что бы то ни было — это прерогатива церкви. </humor>


    1. justhabrauser
      22.04.2018 01:08

      Там после «ни где» можно не читать


      1. Old_Chroft
        22.04.2018 08:34
        +4

        процесс не описан ни где в полной мере и так приступим
        Вообще об ошибках/опечатках принято в личку писать, но тут автор постарался на славу: вся статья является примером абсолютной безграмотности. Но главное в заключении:
        Если понравилась статья, могу ответить в комменты после получения приглашения
        Нет.


  1. impwx
    21.04.2018 23:42

    1. Хабр — это не Gist, для статьи недостаточно выложить кусок кода со словами «ну вот, пользуйтесь». Нужны комменты, объяснение принципа работы, пример.

    2. Я бы подумал, что русский язык для автора не родной. Особенно плохо с пунктуацией. Перед публикацией статью желательно прогонять хотя бы через Word, а еще лучше — дать на вычитку знакомым.


    1. DimaTiunov
      22.04.2018 01:00

      А модерации разве тут нет?


      1. markmariner
        22.04.2018 10:49

        Нет.


      1. wertex15
        22.04.2018 11:29

        Судя по таким вот

        типа статьям
        видимо она прекратила свое существование.


  1. smallplushbear
    22.04.2018 00:54

    1. firedragon
      22.04.2018 01:03

      Вы поклонник написания 100% неповторяемого кода?


      1. smallplushbear
        22.04.2018 01:13

        Я поклонник написания кода.


      1. Leopotam
        22.04.2018 09:16

        Boomburum, копипаста, не являющаяся переводом, на хабре уже разрешена?


        1. firedragon
          22.04.2018 10:18
          -1

          Код подходил под задачу, был добавлен код сохранения с именем файла, написаны заметки по оформлению. Или вы «Правообладатель»?

          PS и этот кусок кода отлично подходил для демонстрации принципа работы.


          1. Leopotam
            22.04.2018 10:26

            habrahabr.ru/info/help/rules

            Заниматься копипастом и кросспостом
            Мы всячески приветствуем интересный и полезный сообществу контент, но только если он оригинальный. Поэтому не следует копипастить на «Хабр» тексты, которые ранее были опубликованы на других ресурсах (даже если вы — автор такого текста).


  1. Alex_ME
    22.04.2018 01:35

    Немного оффтоп: xls — зло. Еще большее зло, что эти форматы (xls, doc и другие) до сих пор стандарт де-факто много где. Старый, проприентарный, бинарный. MS Office Open XML (docx, xlsx, ...) и OpenDocument поддерживаются куда лучше большим количеством современных офисных пакетов.


    1. firedragon
      22.04.2018 09:38
      -2

      Зло он конечно зло, но легаси код и миллионы установок играют свою роль.
      У меня стоит и MS и Libre я чаще использую MS, и только в одном случае использую Calc, когда нужно работать с utf-8 в CSV.
      Отдельный разговор бухгалтерия и всякие контролирующие органы, там засилье MS


  1. ahmpro
    22.04.2018 04:13
    +1

    А TableExport вы смотрели? Возможно у меня чересчур тривиальные случаи, но с особыми проблемами не сталкивался.


    1. firedragon
      22.04.2018 09:49
      -2

      Отличная штука, надо попробовать


  1. ilnuribat
    22.04.2018 04:46

    А вот мне пришлось выгружать данные на стороне ноды, со стилями
    в итоге, забил на стили и просто выгружаю, с модулем xlsx
    Правда при этом сервер потихоньку течет, не знаю почему…
    Хотелось бы услышать, генерировал эксельку с:
    1) форматированием — даже банальный перенос строки в ячейке
    2) комментарии к ячейкам


    1. little-brother
      22.04.2018 05:06
      +1

      Если имеется Windows-машина с установленным Офисом, то на ней можно организовать простенький http-сервис, хоть на Node.js, хоть на Go, принимающий на вход данные и, посредством хоть Windows Script Host, дергать интерфейсы Офиса и выдавать уже готовое в любом нужном формате.


      1. kAIST
        22.04.2018 08:33

        Ну зачем windows. На vds можно использовать какой нибудь LibreOffice, который умеет headless.


      1. ilnuribat
        22.04.2018 13:22

        к сожалению, у нас только линукс серверы


        1. firedragon
          22.04.2018 14:14
          -1

          На сервере как раз намного проще. От предложенного Libre до вполне зрелых решений на PHP и Яве. В случае с сервером есть и еще одно преимущество у вас уже сформирован набор данных, а как его отдать клиенту это вопрос 10й.


    1. eternalego
      22.04.2018 09:19

      К этим пунктом хотелось бы приплюсовать размещение картинок в генерируемом файле.


      1. firedragon
        22.04.2018 09:26
        -1

        У меня эта задача не стояла, но все зависит от движка рендеринга Microsoft Excel. Скорее всего он поймет рисунки встроенные в файл.
        developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs

        например

        <img src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5'>
        


  1. ViceCily
    22.04.2018 08:34

    Как-то приходилось делать подобное для выгрузки из ExtJS в Excel. Сразу отмечу, что к JS/PHP/HTML я имею самое поверхностное отношение:

    // Функция экспорта в Excel с панели табуляции
    function storeToExcel() {
        var aTab = tabPanel.getActiveTab( );
        var aStore = aTab.getStore();  
        Ext.Ajax.request({
            url: 'exportToExcel.php',
            jsonData: Ext.encode(Ext.pluck(aStore.data.items, 'data')),
            success : function(response) {
                if(response.responseText) {
                    window.open("export/" + response.responseText);
                } else {
                    Ext.Msg.alert('Уведомление', 'Ошибка экспорта');
                }
            }
        });
    }


    А сам exportToExcel.php был максимально простой и использовал готовую библиотеку PHPExcel.
    Возможно кому-то такой способ подойдет.


    1. firedragon
      22.04.2018 09:29
      -3

      По моему мнению, это наиболее правильный путь. Серверные компоненты отлично справляются. Но это особенности именно моего проекта.


  1. burfee
    22.04.2018 13:40

    Съехали с SheetJS на exceljs.
    Возможностей стилизации побольше.