1. 程式人生 > >highCharts 轉svg 導出excel

highCharts 轉svg 導出excel

highCharts svg excel

具體的需求是這樣的:

前臺要將查出來的數據用highcharts 展示,包括數據封裝到table中,table 中展示hightchart的圖標,例如這樣

技術分享圖片

這個應該不難實現,那麽這個頁面下面有一個導出按鈕,要將這些數據(table +hightcharts 的圖標)到處成excel 到本地,問題是怎麽將hightcharts 顯示在excel中,理論上報圖標保存為圖片,在workbook中調用圖片也不難,但是現在需要點導出的時候就要生成excel ,這就有點復雜。

具體點的實現是這樣的:在前臺將highchart的數據生成svg ,在後臺將svg 在生成字節流,然後將字節流寫到workbook 中。

代碼如下

前臺的hightcharts 是這樣的:

 var dailyChartObjOption = {
                chart: {
                    renderTo: 'div_survey',
                    margin: [ 50, 10, 40,10],
                    polar: true,
	                type: 'line'
                },
                title: {
                    text: ("網發調研"),
                    floating: true,
                    style: { fontFamily: '上海大眾l,Microsoft YaHei, Verdana, Arial',minWidth:'1170px',fontSize:'16px'}

                },
                pane: {
                    size: '100%'
	            },
                xAxis: {
                    categories:['<%=EnumSurveyType.SQS.getName() %>','<%=EnumSurveyType.CSS.getName() %>','<%=EnumSurveyType.MS.getName() %>','<%=EnumSurveyType.OIC.getName() %>','<%=EnumSurveyType.DCDA.getName() %>'],
                    labels: { 
                        style: { 
                            fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'
                        }
                    },
                    tickmarkPlacement: 'on',
	                lineWidth: 0
                },
                yAxis: {
	                min: 0,
                    max:100,
                    labels: { 
                        enabled:false,
                        style: { 
                            fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'
                        }
                    }
                },
                tooltip: {
                    valueSuffix: '',
                    style: { fontFamily: 'xxxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'},
                    formatter: function() {
                    var y = this.y;
                        if (this.x == "<%=EnumSurveyType.SQS.getName() %>") {
                            y = Math.round(parseFloat(this.y) * 1000)/100;
                        }
                        else if(this.x == "<%=EnumSurveyType.DCDA.getName() %>"){
                            if (this.series.name == "區域平均") {
                                y = Math.round(parseFloat(${dcnAvgScore}) * 100)/100;
                            }
                            else if (this.series.name == "區域最優") {
                                y = Math.round(parseFloat(${dcnTopScore}) * 100)/100;
                            }
                            else{
                                y = Math.round(parseFloat(${dcnScore}) * 100)/100;
                            }
                        }
                        var color_this = color;
                        if (this.series.name == "區域平均") {
                            color_this = colorAvg;
                        }
                        else if (this.series.name == "區域最優") {
                            color_this = colorTop;
                        }
                        return  '<span style="color:'+ color_this +';">' + this.x + '</span><span>:</span><b>' + y + '</b>';
                    }
                },
                exporting: {
                    enabled: false
                },
                credits: {
                    enabled: false
                },
                margin: [0, 0, 0, 0],
                backgroundColor: "#FFF",
                series: [{
                    pointPlacement: 'on',
                    color:colorAvg,
                    name:"區域平均",
                    data: [${sqsAvgScore},${qsssAvgScore},${msAvgScore},${hicAvgScore},${dcnAvgScore}/8]
                },{
                    pointPlacement: 'on',
                    color:colorTop,
                    name:"區域最優",
                    data: [${sqsTopScore},${qsssTopScore},${msTopScore},${hicTopScore},${dcnTopScore}/8]
                },{dataLabels: {
                        enabled: true
                    },
                    pointPlacement: 'on',
                    color:color,
                    name:"${dealerBase.nickName}",
                    data: [${sqsScore},${qsssScore},${msScore},${hicScore},${dcnScore}/8]
                }],
                plotOptions: {
                    line: {
                        marker: {
                                radius: 3
                                },
                        dataLabels: {
                            enabled:false,
                            formatter: function() {
                                var y = this.y;
                                if (this.x == "<%=EnumSurveyType.SQS.getName() %>") {
                                    y = Math.round(parseFloat(this.y) * 1000)/100;
                                }
                                else if(this.x == "<%=EnumSurveyType.DCDA.getName() %>"){
                                    y = Math.round(parseFloat(this.y) * 800)/100;
                                }
                                return  y ;
                            },
                            style: { fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'}
                        },
                        enableMouseTracking: true
                    }
                },
                legend: {
                    enabled :true,
                    itemWidth:itemWidth,
                    borderWidth:0, 
                    y:5,
                    style: { fontFamily: 'xxxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'}
                }
            };
			
            
            var dailyChartObjOptionEn = {
                    chart: {
                        renderTo: 'div_survey_en',
                        margin: [ 50, 10, 40,10],
                        polar: true,
    	                type: 'line'
                    },
                    title: {
                        text: ("SKN Survey"),
                        floating: true,
                        style: { fontFamily: 'xxxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px',fontSize:'16px'}

                    },
                    pane: {
                        size: '100%'
    	            },
                    xAxis: {
                        categories:['<%=EnumSurveyType.SQS.getName() %>','<%=EnumSurveyType.CSS.getName() %>','<%=EnumSurveyType.MS.getName() %>','<%=EnumSurveyType.OIC.getName() %>','<%=EnumSurveyType.DCDA.getName() %>'],
                        labels: { 
                            style: { 
                                fontFamily: 'xxxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'
                            }
                        },
                        tickmarkPlacement: 'on',
    	                lineWidth: 0
                    },
                    yAxis: {
    	                min: 0,
                        max:100,
                        labels: { 
                            enabled:false,
                            style: { 
                                fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'
                            }
                        }
                    },
                    tooltip: {
                        valueSuffix: '',
                        style: { fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'},
                        formatter: function() {
                        var y = this.y;
                            if (this.x == "<%=EnumSurveyType.SQS.getName() %>") {
                                y = Math.round(parseFloat(this.y) * 1000)/100;
                            }
                            else if(this.x == "<%=EnumSurveyType.DCDA.getName() %>"){
                                if (this.series.name == "Average") {
                                    y = Math.round(parseFloat(${dcnAvgScore}) * 100)/100;
                                }
                                else if (this.series.name == "Best") {
                                    y = Math.round(parseFloat(${dcnTopScore}) * 100)/100;
                                }
                                else{
                                    y = Math.round(parseFloat(${dcnScore}) * 100)/100;
                                }
                            }
                            var color_this = color;
                            if (this.series.name == "Average") {
                                color_this = colorAvg;
                            }
                            else if (this.series.name == "Best") {
                                color_this = colorTop;
                            }
                            return  '<span style="color:'+ color_this +';">' + this.x + '</span><span>:</span><b>' + y + '</b>';
                        }
                    },
                    exporting: {
                        enabled: false
                    },
                    credits: {
                        enabled: false
                    },
                    margin: [0, 0, 0, 0],
                    backgroundColor: "#FFF",
                    series: [{
                        pointPlacement: 'on',
                        color:colorAvg,
                        name:"Average",
                        data: [${sqsAvgScore},${qsssAvgScore},${msAvgScore},${hicAvgScore},${dcnAvgScore}/8]
                    },{
                        pointPlacement: 'on',
                        color:colorTop,
                        name:"Best",
                        data: [${sqsTopScore},${qsssTopScore},${msTopScore},${hicScore},${dcnTopScore}/8]
                    },{dataLabels: {
                            enabled: true
                        },
                        pointPlacement: 'on',
                        color:color,
                        name:"${dealerBase.nickNameEn}",
                        data: [${sqsScore},${qsssScore},${msScore},${hicScore},${dcnScore}/8]
                    }],
                    plotOptions: {
                        line: {
                            marker: {
                                    radius: 3
                                    },
                            dataLabels: {
                                enabled:false,
                                formatter: function() {
                                    var y = this.y;
                                    if (this.x == "<%=EnumSurveyType.SQS.getName() %>") {
                                        y = Math.round(parseFloat(this.y) * 1000)/100;
                                    }
                                    else if(this.x == "<%=EnumSurveyType.DCDA.getName() %>"){
                                        y = Math.round(parseFloat(this.y) * 800)/100;
                                    }
                                    return  y ;
                                },
                                style: { fontFamily: 'xxxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'}
                            },
                            enableMouseTracking: true
                        }
                    },
                    legend: {
                        enabled :true,
                        itemWidth:itemWidth,
                        borderWidth:0, 
                        y:5,
                        style: { fontFamily: 'xxx,Microsoft YaHei, Verdana, Arial',minWidth:'1170px'}
                    }
                };

然後在ajax 中將圖標轉成svg

RadaObj = new Highcharts.Chart(dailyChartObjOption);
RadaObjSVG = RadaObj.getSVG();


後臺接收是這樣子的

 HSSFPatriarch patriarch = (HSSFPatriarch) chineseSheet.createDrawingPatriarch();
        // 2進制流
        // 零售銷量
        if (!StringUtils.isEmpty(retailSalesObjSvg)) {
            retailSalesOut = rasterizer.transcode(new ByteArrayOutputStream(), retailSalesObjSvg, MimeType.PNG, null);
            // 零售銷量
            HSSFClientAnchor anchorOne = new HSSFClientAnchor(100, 50, 923, 205, (short) 9, (short) 15, (short) 12,
                (short) 17);
            patriarch.createPicture(anchorOne,
                wb.addPicture(retailSalesOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));

        }

SvgRasterizer svg 轉換的公共類

public class SvgRasterizer {
    /**
     * <p>
     * Description:
     * </p>
     * Field INSTANCE:INSTANCE
     */
    private static final SvgRasterizer INSTANCE = new SvgRasterizer();

    public static final SvgRasterizer getInstance() {
        return INSTANCE;
    }

    /**
     * <p>
     * Description:svg轉換
     * </p>
     * 
     * @param stream 流
     * @param svg svg字符串
     * @param mime mime類型
     * @param width 寬度
     * @return ByteArrayOutputStream 返回值
     * @throws SvgRasterizerException 異常
     * @throws TranscoderException 異常
     * @throws UnsupportedEncodingException 異常
     */
    public synchronized ByteArrayOutputStream transcode(ByteArrayOutputStream stream, String svg, MimeType mime,
        Float width) throws SvgRasterizerException, TranscoderException, UnsupportedEncodingException {
        //TranscoderInput input = new TranscoderInput(new StringReader(svg));
        TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(svg.getBytes("utf-8")));
        TranscoderOutput transOutput = new TranscoderOutput(stream);

        SVGAbstractTranscoder transcoder = getTranscoder(mime);
        if (width != null) {
            transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, width);
        }

        transcoder.transcode(input, transOutput);
        return stream;
    }

    /**
     * <p>
     * Description:獲取轉換器
     * </p>
     * 
     * @param mime mime類型
     * @return SVGAbstractTranscoder 返回值
     * @throws SvgRasterizerException 異常
     */
    public static SVGAbstractTranscoder getTranscoder(MimeType mime) throws SvgRasterizerException {
        SVGAbstractTranscoder transcoder = null;

        switch (mime.ordinal()) {
            case 0:
                transcoder = new PNGTranscoder();
                break;
            case 1:
                transcoder = new JPEGTranscoder();
                transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(0.9D));

                break;
            case 2:
                transcoder = new PDFTranscoder();
                break;
            default:
                break;
        }

        if (transcoder == null) {
            throw new SvgRasterizerException("MimeType not supported");
        }

        return transcoder;
    }
}

這樣就可以了

highCharts 轉svg 導出excel