Copy cells and include headers

Tags: #<Tag:0x00007f0b10dc85d0>

Is there any way to include column headers when using the copy plugin so that headers are included in the copied data?

Selecting the entire grid highlights the headers but a copy then only contains the data cells.

Hi @chris2

At the moment this functionality is unavailable. The requirement has been reported under this issue However, the development of this functionality hasn’t been scheduled yet.

May I ask for the availability for this schedule, this feature actually improves a lot for usability?

Hi @sam.demands, at the moment, we established that the following technique should be enough. If that does not work for your please let me know.

Thanks it work for single header, but nested header do not work.
Seems getColHeader does not return the correct value when there is nested header, it always return null in getColHeader function

That is correct, @sam.demands
The following method does not work for nestedHeaders as the logic is based on colHeaders that do not change when we add nestedHeaders. Now, how to get them. If you do not need to have them merged and in this case


The response can be

D | E | E | E | E | E
2017 | B | C | 12 | 12 | 15

When I recommend saving the header name in cell meta and then attach that cell meta array into the results array in the beforeCopy hook. It’s a theory, and I haven’t tried it. But that should work, if you do not move/hide headers.

Thanks, Budnik,

I fixed that already. But I found that the header always be copied by default, do you have a function showing whether I select the header or not? I would like to ask if I do not select the headers, and do not copy the header by default.

Thanks and Regards
Ivan Cheung

Hi! This is great.
There is a small problem when using CTRL + A and CTRL-C.
The content cells and the header does not align correctly.


If you do not want to copy with colHeaders you need to skip the logic of headers.push(this.getColHeader(i)); and replace it with the data from nestedHeaders.


true, this happens when rowHeaders an enabled so we get this top-left element in header with a name. You can add one additional if to avoid that

if(startRow < 0){ startCol = 0}
for (var i = startCol; i <= endCol; i++) {

Looks like the declaration of startRow is missing in the code.
startRow = ?


yes, it’s similar to the column

startRow is selection[0].from.row

This is working fine with CTRL+A and CTRL+C. Added && startCol < 0

beforeCopy: function(data) {
	var headers = [];
	var selection = this.getSelectedRange();
	var startCol = Math.min(selection[0].from.col, selection[0].to.col);
	var endCol = Math.max(selection[0].from.col, selection[0].to.col);
	var startRow = Math.min(selection[0].from.row, selection[0].from.row);

	if(startRow < 0 && startCol < 0 ){ startCol = 0}
	for (var i = startCol; i <= endCol; i++) {
	data.splice(0, 0, headers);
1 Like


Thanks for your quick response. Actually, I would like to see if there is a property or function to check if I selected the header or not so that I can get a correct copy to decide if I should skip the logic of headers.push(this.getColHeader(i)).

Thanks and Regards
Ivan Cheung

Hey @sam.demands

You can use the response of the afterOnCellMouseDown() hook. It returns -1 for a clicked header.

Hi @sam.demands @dan1 @chris2

I have great news! We’re a single step from introducing a new functionality - Copy with headers.
While we’re doing final tests we’ve opened an issue for the community at

I would be grateful if you could share any translations or just leave a thumbs up :slight_smile: thank you.

Hi guys! It’s here!

We just relased Handsontable v12.3.0 that allows to copy cells with headers and headers only. Here you can read more about the changes.