Gnana
Gnana

Reputation: 77

Highcharts: Export multiple charts using jspdf

When I try to export several Highcharts charts using jsPdf I'm not getting the graph in the proper way.

enter image description here

Could you please help me out in this?

JAVASCRIPT CODE

 Highcharts.chart('container', {

title: {
    text: 'Solar Employment Growth by Sector, 2010-2016'
},

subtitle: {
    text: 'Source: thesolarfoundation.com'
},

yAxis: {
    title: {
        text: 'Number of Employees'
    }
},
legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'middle'
},

plotOptions: {
    series: {
        label: {
            connectorAllowed: false
        },
        pointStart: 2010
    }
},

series: [{
    name: 'Installation',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
    name: 'Manufacturing',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
    name: 'Project Development',
    data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
    name: 'Other',
    data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

});

Highcharts.chart('container1', {

title: {
    text: 'Solar Employment Growth by Sector, 2010-2016'
},

subtitle: {
    text: 'Source: thesolarfoundation.com'
},

yAxis: {
    title: {
        text: 'Number of Employees'
    }
},
legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'middle'
},

plotOptions: {
    series: {
        label: {
            connectorAllowed: false
        },
        pointStart: 2010
    }
},

series: [{
    name: 'Installation',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
    name: 'Manufacturing',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
    name: 'Project Development',
    data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
    name: 'Other',
    data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

});

 Highcharts.chart('container2', {

title: {
    text: 'Solar Employment Growth by Sector, 2010-2016'
},

subtitle: {
    text: 'Source: thesolarfoundation.com'
},

yAxis: {
    title: {
        text: 'Number of Employees'
    }
},
legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'middle'
},

plotOptions: {
    series: {
        label: {
            connectorAllowed: false
        },
        pointStart: 2010
    }
},

series: [{
    name: 'Installation',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
    name: 'Manufacturing',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
    name: 'Project Development',
    data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
    name: 'Other',
    data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

});

 Highcharts.chart('container3', {

title: {
    text: 'Solar Employment Growth by Sector, 2010-2016'
},

subtitle: {
    text: 'Source: thesolarfoundation.com'
},

yAxis: {
    title: {
        text: 'Number of Employees'
    }
},
legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'middle'
},

plotOptions: {
    series: {
        label: {
            connectorAllowed: false
        },
        pointStart: 2010
    }
},

series: [{
    name: 'Installation',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
    name: 'Manufacturing',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
    name: 'Project Development',
    data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
    name: 'Other',
    data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

});

Highcharts.chart('container4', {

title: {
    text: 'Solar Employment Growth by Sector, 2010-2016'
},

subtitle: {
    text: 'Source: thesolarfoundation.com'
},

yAxis: {
    title: {
        text: 'Number of Employees'
    }
},
legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'middle'
},

plotOptions: {
    series: {
        label: {
            connectorAllowed: false
        },
        pointStart: 2010
    }
},

series: [{
    name: 'Installation',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
    name: 'Manufacturing',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
    name: 'Project Development',
    data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
    name: 'Other',
    data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

});
function exportToPdf(){
        var pdf = new jsPDF('p','pt','a4');
          var margins = {
            top: 25,
            bottom: 60,
            left: 20,
            width: 522
          };
         pdf.addHTML(document.body, margins.top, margins.left, {}, function() {
           pdf.save('test.pdf');
         });
    }

HTMl code

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script src='https://cdn.rawgit.com/simonbengtsson/jsPDF/requirejs-fix-dist/dist/jspdf.debug.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/2.3.2/jspdf.plugin.autotable.js'></script>
<script src="https://raw.githubusercontent.com/CBiX/svgToPdf.js/master/svgToPdf.js"></script>
<button onclick="exportToPdf()">
Export
</button>
<div id="container"></div>
<div id="container1"></div>
<div id="container2"></div>
<div id="container3"></div>

If it is not possible with the jsPDf is there any framework that can be used to export the highcharts?

jsFiddle link:

Upvotes: 0

Views: 4593

Answers (1)

Wojciech Chmiel
Wojciech Chmiel

Reputation: 7372

To download multiple charts using jspdf you can use this approach:

  1. send AJAX to Highcharts server with options for each of the charts. The return will be an URL to the image on the server.
  2. convert images from Highcharts server into the base64 format (https://stackoverflow.com/a/20285053/10077925).
  3. Add charts images, logo, footer to pdf using jspdf library and save the result.

Code:

// ############### CHARTS OPTIONS ###############

Highcharts.chart('container1', {
  title: {
    text: 'Chart 1'
  },
  plotOptions: {
    series: {
      label: {
        connectorAllowed: false
      },
      pointStart: 2010
    }
  },
  series: [{
    name: 'Installation',
    color: 'red',
    data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
  }]
});

Highcharts.chart('container2', {
	chart: {
  	type: 'column'		
  },
  title: {
    text: 'Chart 2'
  },
  series: [{
    name: 'Manufacturing',
    color: 'green',
    data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
  }],
});

Highcharts.chart('container3', {
	chart: {
  	type: 'bar'		
  },
  title: {
    text: 'Chart 3'
  },
  subtitle: {
    text: 'Source: thesolarfoundation.com'
  },
  series: [{
    name: 'Sales & Distribution',
    data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
  }]
});

Highcharts.chart('container4', {
  chart: {
    backgroundColor: '#efefef',
    type: 'pie'
  },
  title: {
    text: 'Chart 4'
  },
  series: [{
    name: 'Project Development',
    color: 'purple',
    data: [7988, 12169, 15112, 22452, 34400, 34227]
  }]
});

Highcharts.chart('container5', {
  chart: {
    backgroundColor: '#c5c5c5',
    type: 'spline'
  },
  title: {
    text: 'Chart 5'
  },
  series: [{
    name: 'Project Development',
    color: 'purple',
    data: [7988, 12169, 15112, 22452, 34400, 34227]
  }]
});

// ############### CHARTS OPTIONS ###############


const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }));


$('#btn').click(function() {
  var charts = Highcharts.charts,
    exportUrl = 'https://export.highcharts.com/',
    doc = new jsPDF(),
    pageHeight = doc.internal.pageSize.getHeight(),
    ajaxCalls = [],
    promises = [],
    yDocPos = 0,
    k = 0,
    chart,
    imgUrl,
    i,
    j;

  for (i = 0; i < charts.length; i++) {
    chart = charts[i];
    
    ajaxCalls.push($.ajax({
      type: 'post',
      url: exportUrl,
      data: {
        options: JSON.stringify(chart.userOptions),
        type: 'image/png',
        async: true
      }
    }));
  }

  $.when.apply(null, ajaxCalls).done(function() {

    for (j = 0; j < arguments.length; j++) {
      imgUrl = exportUrl + arguments[j][0];
      promises[j] = toDataURL(imgUrl);
    }

    Promise.all(promises).then((values) => {
      values.forEach((value, index) => {
      	var page = doc.internal.getCurrentPageInfo();
        if (yDocPos > pageHeight - 150) {
          doc.addPage();
          yDocPos = 25;
          k = 0;
        } else {
        	yDocPos = 25 + k * 140;
        }

        doc.setFontSize(30);
        doc.text(50, yDocPos, 'jspdf title for Chart' + (index + 1));
        
        yDocPos += 15;
        doc.addImage(value, 'PNG', 20, yDocPos);
        
        k++;
      });
      doc.save('charts.pdf');
    });
  });
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.4.1/jspdf.debug.js" integrity="sha384-THVO/sM0mFD9h7dfSndI6TS0PgAGavwKvB5hAxRRvc0o9cPLohB0wb/PTA7LdUHs" crossorigin="anonymous"></script>

<button id="btn">Export PDF</button>
<br><br>
<div>
  <div id="container1"></div>
  <div id="container2"></div>
  <div id="container3"></div>
  <div id="container4"></div>
  <div id="container5"></div>
</div>

Demo:

Upvotes: 1

Related Questions