使用 excel-builder.js 的完整示例

问题描述 投票:0回答:3

我需要使用excel-builder.js导出带有样式的excel文件(标题背景颜色蓝色,冻结顶行,列过滤),但是包含所有文档的网站已经无法访问,我什至联系了作者但没有回复。

如果有人可以帮助创建一个包含所有这些格式的小示例,我将非常感激!

我知道以下代码将构建一个 Excel 文件:

var jsonData = [
['sample', 'data', 'for'],
['generating', 'excel', 'in'],
['java', 'script', ' ']
];

require(['excel-builder.js/excel-builder', 'download'], function (EB, downloader) {
    var JSworkBook = EB.createWorkbook();
    var JSworkSheet = JSworkBook.createWorksheet({name: 'Sheet'});

    JSworkSheet.setData(jsonData); 

    JSworkBook.addWorksheet(JSworkSheet);

    var data = EB.createFile(JSworkBook);
    downloader('Artist WB.xlsx', data);
});
javascript excelbuilder.js
3个回答
1
投票

2024 年 9 月 20 日更新:
项目现在维护在这里:https://github.com/ghiscoding/excel-builder-vanilla
感谢@ghiscoding 的出色工作,也对其进行了升级。

原答案如下:

我添加这个只是因为该项目现已被宣布死亡(https://github.com/stephenliberty/excel-builder.js),并且网站文档已离线(http://excelbuilderjs.com/ )。因此,我们能做的最好的事情就是找到愿意用分叉来控制它的人,或者分享我们的代码。

服务器端脚本..

<cfscript>

path="/app/uploads/temp/";
full_path=ExpandPath(path) & FORM.filename;
if (!DirectoryExists(ExpandPath(path))) DirectoryCreate(ExpandPath(path));
FileWrite(full_path,(BinaryDecode(FORM.contents,"Base64")));

json=StructNew();
json.file=path & FORM.filename;
WriteJSON(json);

</cfscript>

你可以使用 PHP..

<?php
header("Content-type: ".$_POST['contentType']);
header("Content-disposition: attachment; filename=\"{$_POST['fileName']}\"");
echo base64_decode($_POST['contents']);
?>

或asp..

[Authorize]
[System.Web.Mvc.SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class SystemController : ApiController {
    private ILog log = LogManager.GetLogger(typeof(SystemController));

    public class ExcelResponse {
        public String FILE = "";
    }
    public class ExcelRequest {
        public String filename;
        public String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        public String contents;
    }

    [HttpPost]
    public ExcelResponse Excel(ExcelRequest request) {
        ExcelResponse response = new ExcelResponse();
        String the_path = "/_assets/temp/";
        String path=System.Web.HttpContext.Current.Server.MapPath("~"+the_path);
        log.Info("Generating excel file from data: "+path+request.filename);
        if (!Directory.Exists(path)) Directory.CreateDirectory(path);
        byte[] file_data=(Convert.FromBase64String(request.contents));
        File.WriteAllBytes(path + request.filename, file_data);
        response.FILE = the_path+request.filename;
        return response;
    }
}

还有包含脚本...

require.config({
    baseUrl: '/app/assets/',
    paths: {
            underscore: '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min',
            JSZip: './excel-builder/jszip',
            EB: './excel-builder.dist.min',
            spin: '//cdnjs.cloudflare.com/ajax/libs/spin.js/1.2.7/spin.min',
            image: '/3rdparty/requirejs/image',
            text: '/3rdparty/requirejs/text',
            util: '/excel-builder/Excel/util'
    },
    shim: {
            'underscore': {
                    exports: '_'
            },
            'JSZip': {
                    exports: 'JSZip'
            },
            'swfobject': {
                    exports: 'swfObject'
            }
    }
});

进入./excel-builder/download.js

define(function () {
    return function (fileName, content) {
        var form = $("<form id='download'>").attr({
            target: '_BLANK',
            action: '/app/assets/excel-builder/excel.cfm',
            method: 'post'
        }).css({display: 'none'});
        form.append($("<input>").attr({name: 'fileName', value: fileName}));
        form.append($("<input>").attr({name: 'contentType', value: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}));
        var ta=$("<textarea>").attr({name: 'contents', value: content});
        ta.val(content);
        form.append(ta);
        form.appendTo($("body"));
        form.submit();
        window.setTimeout(function () {form.remove();}, 30000);
    }
});

引导程序(用于表格排序器)...

$(document).ready(function() {
    $("table.sort").on("filterEnd",ts_onTableFiltered);
});

它的肉...

function ts_onTableFiltered(event,tblsorter) {
    $(tblsorter.table).data('ts_sorter',tblsorter);/*legacy :: */ window.ts_currentSorter=tblsorter;
    console.log(event.type);
    
    $(tblsorter.table).data('ts_isFiltered',false); /*legacy. remove me after verification :: */ window.ts_isFiltered=false;
    for (var i=0;i<tblsorter.lastSearch.length;i++) {
        var currentItemFilter=((tblsorter.lastSearch[i]!="")?true:false);
        if (currentItemFilter) {
            $(tblsorter.table).data('ts_isFiltered',true);/* legacy:: */ts_isFiltered=true;
            break;
        }
    }
    var rows=[];
    if ($.isEmptyObject( tblsorter.cache )) {
        rows=tblsorter.$tbodies.eq( 0 ).children( 'tr' );
    } else {
        for(i=0;i<tblsorter.cache[0].normalized.length;i++) {
            var row=tblsorter.cache[0].normalized[i][tblsorter.columns].$row[0];
            if (!ts_isFiltered) {rows.push($(row));continue;}
            
            var result=tblsorter.pager.regexRows.test(row.className);
            if (!result) { // skip 'filtered' className
                rows.push($(row));
            }
        }
    }
    
    $(tblsorter.table).data('ts_currentRowsInTable',rows); /*legacy :: */window.ts_currentRowsInTable=rows;
    console.log(rows.length);
    
}
function downloadExcelFromTable(tableObj,filename,props) {
    var button=$('a:contains("Excel")');
    if (button.length > 1) {
        var temp=0;
        button.each(function() {
            if ($(this).attr('onclick').indexOf(tableObj.attr('id'))>=0) {
                temp=$(this);
            }
        });
        //button=temp;
    }
    console.log("Generating document...");
    var orig_data = [];
    var headers=[];
    var headers_text_len_max=0;
    
    var excel_wait_html='<i class="fa fa-spinner fa-pulse"></i> Please wait...';
    button.data('orig-html',button.html());button.html(excel_wait_html);
    
    if (tableObj.data('ts_currentRowsInTable').length<1 || (tableObj.data('ts_currentRowsInTable').length==1 && tableObj.find('tr:contains("No known")').length>0)) {
        return BootstrapMessage("Cannot download Excel document","Sorry but there aren't any result rows to populate an excel document. Please refine your report/resultant listing.",function() {
            button.html(button.data('orig-html'));
        });
    }
    var doSetupProperties=false;
    if (typeof(props)==='undefined') {props={};}
    if (typeof(props.column_widths)==='undefined') {
        doSetupProperties=true;
        props.column_widths=[];
        props.column_widths_auto=[];
        props.maxWidthPerRow=[];
    }
    
    var filterChosen=false;
    if (tableObj.hasClass("selectable")) filterChosen=true;
    
    var ignoreCols=[];
    var i=0;
    tableObj.find('th').each(function() {
        if ($(this).text().length<1) ignoreCols.push(i);
        else {
            headers.push($(this).text());
            props.maxWidthPerRow.push(0);
            headers_text_len_max+=$(this).text().length;
        }
        i++;
    });
    orig_data.push(headers);
    console.log("Headers done.");
    
    
    
    var handleRow=function(row,ignoreCols) {
        var col_i=0;
        row.find('td').each(function() {
            if ($.inArray(col_i,ignoreCols)<0) {
                var text=$(this).text().split('\n').join('').trim();
                if ($(this).hasClass('sorter-select')) {
                    text=$(this).find('select:first').val();
                }
                var contents=text;
                if (tableObj.hasClass('attachTotalsRow')) {
                    if ((''+tableObj.data('totals_columns')).indexOf(col_i+1)!=-1) {
                        text=(text.replace('$',''));
                        contents=parseFloat(text);
                    }
                    
                    //row_data.push({value: text,metadata: {style: }});
                    //row_data.push(parseFloat(text));
                }
                row_data.push(contents);
                
                var href=$(this).find('a');
                if (href.length>0) {
                    var url=href.attr('href');
                    row_data[row_data.length-1]={value: 'HYPERLINK("'+url+'","'+text+'")', metadata: { type: 'formula' }};
                }
                if (text.length > props.maxWidthPerRow[col_i]) props.maxWidthPerRow[col_i]=text.length;
            }
            col_i++;
        });
        return (row_data);
    }
    
    if (tableObj.hasClass('tablesorter')) {
        /*its tablesorter, so we need to obtain all of the hidden filtered data too. */
        var rows=tableObj.data('ts_currentRowsInTable');
        for (i=0;i<rows.length;i++) {
            var row_data=[];
            var row = $(rows[i]);
            /*if (filterChosen && !isNaN(tableObj.data('chosen'))) {
                var target=row.find('td:nth-child('+tableObj.data('chosen')+' input[type=checkbox]');
                if (target.length==1) {
                    if (!target.prop('checked')) continue;
                }
            }*/
            orig_data.push(handleRow(row,ignoreCols));
        }
        
        
    } else {
        tableObj.find('tbody tr').each(function() {
            var row_data=[];
            var row=$(this);
            orig_data.push(handleRow(row,ignoreCols));
        });
    }
    if (tableObj.hasClass('attachTotalsRow')) {
        var list_cols=tableObj.data('totals_columns');
        if (isNaN(list_cols)) {
            var av_cols=list_cols.split(',');
        } else {
            var av_cols=[list_cols];
        }
        av_cols=av_cols.sort();
        var max=orig_data.length;
        var min=2; // skip header row
        
        var new_totals_row=[];
        for (var ii=0;ii<headers.length;ii++) {
            new_totals_row[ii]="";
        }
        for (var i=0;i<av_cols.length;i++) {
            var colIdent=String.fromCharCode(64+av_cols[i]);
            new_totals_row[0]="Totals:"
            new_totals_row[av_cols[i]-1]={value: 'SUM('+((colIdent+min)+':'+(colIdent+max))+')',metadata: {type: 'formula'}};
        }
        orig_data.push(new_totals_row);
    }
    
    // adjust column widths to fit their text.
    if (doSetupProperties) {
        var maxDigitWidth=8;
        var padding=22;
        var fn_truncate=function(num) {return Math.round(num*100)/100;};
        var fn_calcWidth=function(numchars,maxdigit,pad) {return fn_truncate(((numchars *  maxdigit + pad)/maxdigit*256)/256   );};
        var fn_calcPixels=function(p_width,maxdigit){return fn_truncate(((256 * p_width + fn_truncate(128/maxdigit))/256)*maxdigit);};
        for (var i=0;i<headers.length;i++) {
            var perc_size_of_whole=(100/headers_text_len_max)*headers[i].length;
            //props.column_widths.push({width: perc_size_of_whole*1.5});
            //props.column_widths_auto.push({bestFit: true,width: maxWidthPerRow[i]});
            props.column_widths.push({width: (fn_calcWidth(props.maxWidthPerRow[i],maxDigitWidth,padding)) });
        }
    }
    console.log(props);
    
    console.log("Row data done.");
     
    require(['excel-builder/excel-builder', 'excel-builder/Excel/Table','excel-builder/download'], function (EB, Table, downloader) {
        console.log("Beginning excel creation.");
        var workbook = EB.createWorkbook();
        var worksheet = workbook.createWorksheet({name: filename});
     
        
     
        var stylesheet = workbook.getStyleSheet();
        var currency = stylesheet.createFormat({
            format: '$#,##0.00'
        });
        var boldDXF = stylesheet.createDifferentialStyle({
            
            font: {
                italic: true,
                size: 12
            }
        });
     
        var sheetStyle=stylesheet.createTableStyle({
            name: 'SlightlyOffColorBlue',
            wholeTable: boldDXF.id,
            headerRow: stylesheet.createDifferentialStyle({
                alignment: {horizontal: 'center'},
                font: {
                    size: 13,
                    bold: true
                }
            }).id
        });
        console.log("Styles applied.");
     
        
        var table = new Table();
        table.styleInfo.themeStyle = "SlightlyOffColorBlue"; //"TableStyleDark2"; //This is a predefined table style
        table.setReferenceRange([1, 1], [headers.length, orig_data.length]); //X/Y position where the table starts and stops.
     
        //Table columns are required, even if headerRowCount is zero. The name of the column also must match the
        //data in the column cell that is the header - keep this in mind for localization
        table.setTableColumns(headers);
        console.log("headers configured.");
     
        worksheet.setData(orig_data);
        worksheet.setColumns(props.column_widths)
        //worksheet.setColumnFormats(props.column_widths_auto);
        workbook.addWorksheet(worksheet);
     
        worksheet.addTable(table);
        workbook.addTable(table);
        console.log("tables configured.");
        
        var dt=new Date();
        var file= replaceAll(filename," ","_") +"_"+ (dt.getFullYear()+"-"+dt.getMonth()+"-"+dt.getDate()+"_"+dt.getMilliseconds())+'.xlsx';
        file=replaceAll(file,"/","_"); file=replaceAll(file,"\\","_");
        var data = EB.createFile(workbook);
        console.log("workbook generated. File generation commensing: ");
        //downloader(file, data);  // this uses the downloader.js file. Disabled as I am customizing the ajax call completely... as follows..
        
        /*legacy attempt..     var contents=''+
            '<form method="POST" action="/app/assets/excel-builder/excel.cfm" enctype="application/x-www-form-urlencoded">'+
                '<input type="hidden" name="filename" value="'+file+'" />'+
                '<input type="hidden" name="contentType" value="'+('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')+'" />'+
                '<input type="hidden" name="contents" value="'+data+'" />'+
                
                '<input type="submit" value="Download Now" class="button print" />'+
            '</form>';*/
        var dat={
            filename: file,
            contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            contents: data
        };
        $.ajax({
            url: '/app/assets/excel-builder/excel2.cfm',
            type: "POST",
            data: dat,
            success: function(result) {
                result=$.parseJSON(result);
                console.log("Response received. File is located here: "+result.FILE);
                if (typeof(onExcelDocGenerated)==='function') onExcelDocGenerated(); // optional callback (global)
                contents='<a style="color: lightgreen;" href="'+result.FILE+'" class="button print" >Download Now</a>';
                $.notice("Confirm Excel Download",contents,"Cancel",function() {
                    button.html(button.data('orig-html'));
                    if (typeof(excel_download_done)==='function') {
                        excel_download_done(); // optional callback (global)
                    }
                },function() {
                    button.html(button.data('orig-html'));
                    if (typeof(excel_download_done)==='function') {
                        excel_download_done();
                    }
                });
            },
            error: function(e) {
                console.log("Fatal networking error: "+e);
            }
        });
            
    });
}

以及页面上的实现..

        <a href="#" id="exceldownload" onclick="try {downloadExcelFromTable($('table'),'My Report');}catch(e){alert('failed due to error: '+e);};return false;" class="button print table-excel">
            <i class="fa fa-file-excel-o"></i> Excel
        </a>

这是一个表格排序器的完整实现,支持插入 Excel 工作表中的链接,甚至通过简单地将类(.attachTotalsRow)添加到表类 attr 来求和(总计)行。 甚至支持过滤,因此它只抓取由 Excel 表排序器过滤的行,并根据文本宽度自动调整列大小。 您可以看到有几个部分正在开发中,并且有大量稀疏的注释和控制台日志,但它确实有效。 上面是为 ajax 调用设计的,它在 JSON 响应中提供了文件的路径。这样您就可以使用所有设备都支持的浏览器本机点击。通过 javascript 打开新窗口是不安全的,因此这就是采用该方法的原因。因此,顶部的 php 脚本需要更新以模仿 Coldfusion 脚本。

您想要的部分位于 ajax 调用之前的底部。 祝你好运!


1
投票

您可以通过 网络存档 访问文档的缓存版本。 但请记住,您需要使用缓存 url 语法在文档页面之间导航,而不是仅仅单击链接。


0
投票
        var workbook = ExcelBuilder.Builder.createWorkbook();
        var stylesheet = workbook.getStyleSheet();
        var sheet1 = workbook.createWorksheet({
                    name: 'Data1'
                });
        var headings = stylesheet.createFormat({
                    "fill": {
                        "type": 'pattern',
                        "patternType": 'solid',
                        "fgColor": '4BACC6'
                    }
                });
        var jsonData = [
        [{value:'sample', metadata: {style: headings.id}}, {value:'data', metadata: {style: headings.id}}, {value:'for', metadata: {style: headings.id}}],
        ['generating', 'excel', 'in'],
        ['java', 'script', ' ']
        ];
        sheet1.setData(jsonData);
        workbook.addWorksheet(sheet1);
                ExcelBuilder.Builder.createFile(workbook, {
                    type: "blob"
                }).then(function(data) {
                    saveAs(new Blob([data], {
                        type: "base64"
                    }), "Demo.xlsx");
                });
© www.soinside.com 2019 - 2024. All rights reserved.