npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

copy-excel-chart

v1.0.23

Published

Copy .xlsx charts between .xlsx files.

Downloads

14

Readme

WARNING: The XML schema can very between charts and additional testing is necessary to prove that this library works for all chart types

Consider using excels internal JavaScript API BEFORE using this library.
If Excel is not available in your working environment and you still need to copy excel charts using JavaScript, consider using this library as a code example and thoroughly test your use cases before deploying.
XML schema can differ between each chart type and this library has not been thoroughly tested using all possible chart type and user configurations. Use with discretion.

Copy charts between excel files using Node file system operations.

Currently working with basic excel .xlsx charts, that pull data from cell ranges. Not yet tested with pivot charts or charts that reference named ranges or tables. Excel chart XML schemas that create a new xml section for each x axis heading may not be supported

Dependencies:

xm2js : Used to convert excel .xml source files into JSON objects. AdmZip : Used to unzip .xlsx files into individual .xml files

Installation

npm i copy-excel-chart

Working Code Example, additional explanation shown below under "Usage" heading:

All Excel files used in these examples can be found in the test folder of this package.

import copyExcelChart from 'copy-excel-chart'
import fs from 'fs'
const readCharts = copyExcelChart.readCharts
const copyChart = copyExcelChart.copyChart
const writeCharts = copyExcelChart.writeCharts

async function test(){

    if(!fs.existsSync('./working')) fs.mkdirSync('./working')

    const source = await readCharts('./source.xlsx', './working')
    const output = await readCharts('./target.xlsx', './working')

    const replaceCellRefs = source.summary()['chartWorksheet']['chart1'].reduce((acc, el)=>{
        return {...acc, [el]: el.replace('recommendWorksheet2', 'worksheet-Recommendation')}
    }, {})

    copyChart(
        source,
        output,
        'chartWorksheet',
        'chart1',
        'worksheet-Recommendation',
        replaceCellRefs,
    )

    writeCharts(output, './product.xlsx')

    fs.rmdirSync('./working', { recursive: true })
}

test()

Usage:

Setup imports

import copyExcelChart from 'copy-excel-chart'
import fs from 'fs'

Setup shortcuts:

const readCharts = copyExcelChart.readCharts
const copyChart = copyExcelChart.copyChart
const writeCharts = copyExcelChart.writeCharts

Create a working folder. Make sure fs is imported!

if(!fs.existsSync('./working')) fs.mkdirSync('./working')

Read an excel file that contains source charts using the readCharts() function.

const source = await readCharts('./source.xlsx', './working')

Run source.summary() to get a list of worksheets, each worksheets charts, and each charts cell references.

Function source.summary()
console.log('Worksheet Summary:', source.summary())

> Worksheet Summary: {
>    recommendWorksheet2: {}, //worksheet with no charts
>    earningsWorksheet1: {}, //worksheet with no charts
>        cashWorksheet4: {}, //worksheet with no charts
>    candleWorksheet3: {}, //worksheet with no charts
>    chartWorksheet: { //worksheet with 4 charts.
>        chart3: [ //chart3 cell reference array
>            'cashWorksheet4!$B$2:$B$22',
>            'cashWorksheet4!$C$2:$C$22',
>            'cashWorksheet4!$C$1'
>        ],
>        chart2: [ //chart2 cell reference array
>            'candleWorksheet3!$B$2:$B$26',
>            'candleWorksheet3!$C$2:$C$26',
>            'candleWorksheet3!$B$2:$B$27',
>            'candleWorksheet3!$D$2:$D$26',
>            'candleWorksheet3!$E$2:$E$26',
>            'candleWorksheet3!$F$2:$F$26',
>            'candleWorksheet3!$C$1',
>            'candleWorksheet3!$D$1',
>            'candleWorksheet3!$E$1',
>            'candleWorksheet3!$F$1'
>        ],
>        chart1: [ //chart1 cell reference array
>            'recommendWorksheet2!$B$2:$B$42',
>            'recommendWorksheet2!$C$2:$C$42',
>            'recommendWorksheet2!$D$2:$D$42',
>            'recommendWorksheet2!$E$2:$E$42',
>            'recommendWorksheet2!$F$2:$F$42',
>            'recommendWorksheet2!$G$2:$G$42',
>            'recommendWorksheet2!$C$1',
>            'recommendWorksheet2!$D$1',
>            'recommendWorksheet2!$E$1',
>            'recommendWorksheet2!$F$1',
>            'recommendWorksheet2!$G$1'
>        ],
>        chartEx1: [ //chartEx1 cell reference array
>            'earningsWorksheet1!$B$2:$B$22',
>            'earningsWorksheet1!$C$1',
>            'earningsWorksheet1!$C$2:$C$22'
>        ]
>    }
> }

Repeat the steps from above for the excel xlsx file that your will be copying charts into. Note that excel assigns chart names behind the scenes and sequences their names based on schema type. Chart and ChartEx and charts that use different XML schemas. Any chart that is not of type "chart" or "chartEx" probable has not been tested and this library might not be able to copy.

const output = await readCharts('./target.xlsx', './working')
console.log('Worksheet Summary:', output.summary())

> Worksheet Summary: {
>  'worksheet-candle': {}, //worksheet with no charts
>  'worksheet-Recommendation': {}, //worksheet with no charts
>  'worksheet-EBIT': {}, //worksheet with no charts
>  'worksheet-cashRatio': {} //worksheet with no charts
> }

Create a cell reference replacement object. This step is necessary if the chart being copied needs updated cell references that point to a new location. Replacement Object: {[old reference]: new reference} example: {oldworksheet!A1:B20: newWorksheet!A1:B15} The Reducer function below creates an object that will be used to replace chart1's cell references with new references that point to the worksheet 'worksheet-Recommendation' instead of worksheet 'recommendWorksheet2'.

const replaceCellRefs = source.summary()['chartWorksheet']['chart1'].reduce((acc, el)=>{
    return {...acc, [el]: el.replace('recommendWorksheet2', 'worksheet-Recommendation')}
}, {})
console.log('Cell Reference overrides:', replaceCellRefs)
> Cell Reference overrides:
> {
>  'recommendWorksheet2!$B$2:$B$42': 'worksheet-Recommendation!$B$2:$B$42',
>  'recommendWorksheet2!$C$2:$C$42': 'worksheet-Recommendation!$C$2:$C$42',
>  'recommendWorksheet2!$D$2:$D$42': 'worksheet-Recommendation!$D$2:$D$42',
>  'recommendWorksheet2!$E$2:$E$42': 'worksheet-Recommendation!$E$2:$E$42',
>  'recommendWorksheet2!$F$2:$F$42': 'worksheet-Recommendation!$F$2:$F$42',
>  'recommendWorksheet2!$G$2:$G$42': 'worksheet-Recommendation!$G$2:$G$42',
>  'recommendWorksheet2!$C$1': 'worksheet-Recommendation!$C$1',
>  'recommendWorksheet2!$D$1': 'worksheet-Recommendation!$D$1',
>  'recommendWorksheet2!$E$1': 'worksheet-Recommendation!$E$1',
>  'recommendWorksheet2!$F$1': 'worksheet-Recommendation!$F$1',
>  'recommendWorksheet2!$G$1': 'worksheet-Recommendation!$G$1'
> }

Copy a chart from the source working files to the output working files using the copyChart() function. Note that each time copyChart runs it edits the output file.xml(s) and updates the output object with all changes.

copyChart(
    source,
    output,
    'chartWorksheet',
    'chart1',
    'worksheet-Recommendation',
    replaceCellRefs,
)

If additional charts need to be copied do so here by performing addtional copyChart() operations.

Write a new excel file: product.xlsx from the output working file using the writeChart() function

writeCharts(output, './product.xlsx')

Clean up old files

fs.rmdirSync('./working', { recursive: true })

API

copyExcelChart.readCharts()

Returns an object that DETAILS worksheet chart relationships. Return type includes helper method, .summary(), that SUMMARIZES worksheet chart relationships .summary() should be significantly easier to run looping functions against than the detail.

Function readCharts(
    source File: string,        //The path of the excel file you will be copying charts from
    working directory: string,  //a temporary working directory for file read/write operations.
)

copyExcelChart.copyChart()

Updates toObject .xml files and updates updates toObject relationships. Copies a single chart. Run multiple times, with additional chart names, to copy multiple charts.

Function copyChart(
    fromObject: readCharts() return object,
    toObject: readCharts() return object,
    source worksheet: string,                    //source worksheet name is the worksheet alias viewable in an excel workbook
    source chart: string,                        //source chart name can be found using readCharts().summary()
    move to worksheet: string,                   //worksheet name visible in the output excel workbook.
    cell reference overrides:{[string]: string}, //object containing key value pairs that are used to update cell references. ex: {worksheet1!A1:B2: newWorksheet: C1:D2}
)

copyExcelChartt.writeChart()

From the provided objects .xml files, write a new excel file.

Function writeChart(
    toObject: readCharts() return object,
    file name: string
)

Run the tests:

> git clone https://github.com/GlennStreetman/copyExcelChart.git
> cd copyExcelChart
> npm install

Use your file explorer to open the tests subdirectory and review each sub-directories files.

> node runTests

At this point each sub-directory will have a new "product.xlsx" file as well as a new sub-folder named "working".
product.xlsx is a copy of target.xlsx with source.xlsx's charts copied over.
The "working" sub-directory contains that chart source, and destination XLSX files, XML source files.