72

I was wondering if anybody knows how to select using js the complete table, so that the user can right-click on the selection, copy it to the clipboard and then paste it on Excel. If you select the table manually, the process works perfectly. But sometimes, if the table height is a few times larger than the screen, selecting it dragging the mouse gets tedious. So, I want to give the users the possibility to click on a "select the whole table" button and everything gets ready to be copied.

Any ideas?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
DanC
  • 8,595
  • 9
  • 42
  • 64

4 Answers4

113

Yes. It's not too tricky, and the following will work in all mainstream browsers (including IE 6, and indeed 5):

(Updated 7 September 2012 after Jukka Korpela's comment pointing out that the previous version didn't work in IE 9 standards mode)

Demo: http://jsfiddle.net/timdown/hGkGp/749/

Code:

function selectElementContents(el) {
 var body = document.body, range, sel;
 if (document.createRange && window.getSelection) {
  range = document.createRange();
  sel = window.getSelection();
  sel.removeAllRanges();
  try {
   range.selectNodeContents(el);
   sel.addRange(range);
  } catch (e) {
   range.selectNode(el);
   sel.addRange(range);
  }
 } else if (body.createTextRange) {
  range = body.createTextRange();
  range.moveToElementText(el);
  range.select();
 }
}
<table id="tableId" border="1">
 <thead>
  <tr><th>Heading 1</th><th>Heading 2</th></tr>
 </thead>
 <tbody>
  <tr><td>cell 1</td><td>cell 2</td></tr>
 </tbody>
</table>

<input type="button" value="select table" onclick="selectElementContents( document.getElementById('tableId') );">
saAction
  • 2,035
  • 1
  • 13
  • 18
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • On IE 9, this does not work in “Standards Mode”. The console shows an error message about failure to complete an action, with error code 800a025e, related to the line `range.select();`. In Quirks Mode, and also when browser mode set to IE 8, it works. – Jukka K. Korpela Sep 05 '12 at 08:23
  • @JukkaK.Korpela Interesting, thanks. I've updated my answer with a workaround. – Tim Down Sep 07 '12 at 14:05
  • Great solution. Adding just one more hint, if, like me, you want this to happen without causing a redraw: 1. have selectElementComments return false (i.e. add `return false;` as last line of selectElementComments. 2. use `onclick="return selectElementContents(.....)` – gkakas Apr 27 '14 at 08:32
  • Thank you and copy clipbord pls – alpc Jan 09 '15 at 12:29
  • Sure it selects the table, but how do you automatically copy it to the clipboard? Not ideal that the user still has to press ctrl-c or copy-paste. – Jason Ebersey Apr 30 '15 at 11:50
  • This worked after I replaced the selector getElementById() with querySelector() instead, in case anyone else runs into the same issue. – Aaron Belchamber Jan 30 '17 at 14:25
  • @AaronBelchamber: ... in which case what you were passing to `document.getElementById()` wasn't the ID of the element you were interested in. I shall update the answer to be a little more explicit. – Tim Down Jan 30 '17 at 15:25
  • Well, I'm pretty sure it was the proper ID, it just didn't work for me, at least tested on FF, 51.0.1. But thanks for assuming it must be user error LOL – Aaron Belchamber Jan 30 '17 at 20:23
  • @AaronBelchamber: Obviously you're welcome to use `querySelector()` but `document.getElementById()` is rock-solid so if it's not working then it's overwhelmingly likely to be user error. Everyone makes errors; realising and acknowledging when it's likely that you've made one is one of the major skills of being a developer. – Tim Down Jan 31 '17 at 11:34
  • Is it possible to alter this to only select certain rows and columns of a table, and not the complete table? – Steve Nov 18 '18 at 18:16
  • @Steve: The answer is mostly no. In Firefox only you can select multiple [ranges](https://developer.mozilla.org/en-US/docs/Web/API/Range) so you could select any combination of content you like, including table cell content, but in other browsers you can only select one range (which is a single contiguous part of a document, defined by a start and end boundary), which means you could select one part of a table but not multiple discontiguous parts of it. – Tim Down Nov 20 '18 at 15:48
  • Thanks Tim - I was able to get it working (only tested in Chrome) by removing the row, then copying to clipboard, and re-adding the row back. It happens so fast I can't even see it. – Steve Nov 21 '18 at 15:51
18

Just to make the code proposed by Tim Down more complete, allowing de selected content to be automatically copied to clipboard:

<script type="text/javascript">
    function selectElementContents(el) {
        var body = document.body, range, sel;
        if (document.createRange && window.getSelection) {
            range = document.createRange();
            sel = window.getSelection();
            sel.removeAllRanges();
            try {
                range.selectNodeContents(el);
                sel.addRange(range);
            } catch (e) {
                range.selectNode(el);
                sel.addRange(range);
            }
            document.execCommand("copy");

        } else if (body.createTextRange) {
            range = body.createTextRange();
            range.moveToElementText(el);
            range.select();
            range.execCommand("Copy");
        }
    }
</script>

<table id="tableId">
    <thead>
        <tr><th>Heading</th><th>Heading</th></tr>
    </thead>
    <tbody>
        <tr><td>cell</td><td>cell</td></tr>
    </tbody>
</table>

<input type="button" value="select table"
   onclick="selectElementContents( document.getElementById('tableId') );">
Daniel
  • 301
  • 2
  • 4
  • It's copying an extra blank row at the top, any idea on how to remove this? There isn't a blank row in the HTML – NeoTechni Mar 02 '22 at 16:22
7

I got it to work in IE9 finally by using the following script

NOTE: It doesn't work on html tables. It HAS to be a DIV. So just put a wrapper DIV around the table you need to select!

First I changed the HTML button code a bit:

<input type="button" value="Mark table"    onclick="SelectContent('table1');">  

Then changed the javascript to:

function SelectContent (el) {


var elemToSelect = document.getElementById (el);

        if (window.getSelection) {  // all browsers, except IE before version 9
            var selection = window.getSelection ();
            var rangeToSelect = document.createRange ();
            rangeToSelect.selectNodeContents (elemToSelect);

            selection.removeAllRanges ();
            selection.addRange (rangeToSelect);



        }

    else       // Internet Explorer before version 9
          if (document.body.createTextRange) {    // Internet Explorer
                var rangeToSelect = document.body.createTextRange ();
                rangeToSelect.moveToElementText (elemToSelect);
                rangeToSelect.select ();

        }

  else if (document.createRange && window.getSelection) {         
          range = document.createRange();             
          range.selectNodeContents(el);             
    sel = window.getSelection();     
                  sel.removeAllRanges();             
    sel.addRange(range);              
 }  
}
  • I finally got this to work when I pointed to an encasing
    so onclick="SelectContent('dv');" ...........
    data
    – gordon Dec 18 '14 at 23:17
1

Here is what I have used. It also make the copy command so all you have to do is use the paste command in the document you want to place it into. Basically you wrap the content you want to copy in a div, grab it using innerHTML and copy it to the clipboard. I have not tested it on all browsers but it works in Chrome, Safari, Firefox.

<div id="copycontent">
<table>
</table>
</div>
<input type="button" value="Mark table"    onclick="SelectContent('copycontent');">

<script type="text/javascript">
function SelectContent (el) {    
  var aux = document.createElement("div");
  aux.setAttribute("contentEditable", true);
  aux.innerHTML = document.getElementById("main").innerHTML;
  aux.setAttribute("onfocus", "document.execCommand('selectAll',false,null)"); 
  document.body.appendChild(aux);
  aux.focus();
  document.execCommand("copy");
  document.body.removeChild(aux);
}
</script>
Mark Parrish
  • 326
  • 2
  • 10