I want to copy the second row of an html table to paste it in an excel file. My code works perfectly with firefox, I can paste it in excel and one table cell matches one excel cell. However, when using chrome, when I paste the code in excel, the cells don't match and only the html inside the table cells are retained. I am using vue, here is a link to an example: https://playcode.io/910728
It does work properly when the ref is written in the element, but then I have the heading inside the copied values, which I don't want.
and here is my code:
<script setup>
import {ref} from 'vue'
let matable = [
{ "name": "Link pic", "id": 34, "champ": "<p> Here is a link: <a href='www.google.com'> Link image</a> <br><br>" },
{ "name": "Source", "id": 16, "champ": "electricity" },
{ "name": "Generator", "id": 15, "champ": "Chaudière" },
{ "name": "Canton", "id": 1, "champ": "GE" },
{ "name": "City", "id": 2, "champ": "Paris" },
{ "name": "Numéro de rue", "id": 3, "champ": "72" },
{ "name": "Nom de rue", "id": 4, "champ": "Rue du Président" },
{ "name": "Surface facades", "id": 36, "champ": 2175.42 },
]
const elTable = ref(null)
defineExpose({ elTable });
function selectElementContents(){
let range, sel;
// Ensure that range and selection are supported by the browsers
if (document.createRange && window.getSelection) {
range = document.createRange();
sel = window.getSelection();
// unselect any element in the page
sel.removeAllRanges();
try {
range.selectNodeContents(elTable.value);
sel.addRange(range);
} catch (e) {
range.selectNode(elTable.value);
sel.addRange(range);
}
document.execCommand('copy');
}
}
</script>
<template>
<h1>Hello Vue 3</h1>
<table ref="elTable">
<thead>
<th
v-for="ma in matable"
:key="ma.id">
{{ ma.name}}
</th>
</thead>
<tbody >
<tr >
<td v-for="ma in matable"
:key="ma.id"
v-html="ma.champ"
>
</td>
</tr>
</tbody>
</table>
<input type="button" value="Copier" ref="copy" v-on:click="selectElementContents">
</template>
<style scoped>
</style>
I also tried to build a specific function for chrome with the clipboard api, but with no luck so far. I does copy, but it doesn't keep the same cell layout like the firefox version. Here is the try out:
function testCopy(){
let table = matable.map(a => a.champ);
let contentCo = table.join(" ");
console.log("voici ma table",contentCo)
navigator.permissions.query({ name: 'clipboard-write' }).then(result => {
if (result.state === 'granted') {
var blob = new Blob([contentCo], {type: 'text/html'});
var item = new ClipboardItem({'text/html': blob});
navigator.clipboard.write([item]).then(function() {
console.log("Copied to clipboard successfully!");
}, function(error) {
console.error("unable to write to clipboard. Error:");
console.log(error);
});
} else {
console.log("clipboard-permission not granted: " result);
}
})
CodePudding user response:
I might have a workaround. It's not perfect but it works.
The idea is to add a second table under the first one with the ref at the root of the table, then make it hidden with css.
<script setup>
import {ref} from 'vue'
let matable = [
{ "name": "Link pic", "id": 34, "champ": "<p> Here is a link: <a href='www.google.com'> Link image</a> <br><br>" },
{ "name": "Source", "id": 16, "champ": "electricity" },
{ "name": "Generator", "id": 15, "champ": "Chaudière" },
{ "name": "Canton", "id": 1, "champ": "GE" },
{ "name": "City", "id": 2, "champ": "Paris" },
{ "name": "Numéro de rue", "id": 3, "champ": "72" },
{ "name": "Nom de rue", "id": 4, "champ": "Rue du Président" },
{ "name": "Surface facades", "id": 36, "champ": 2175.42 },
]
function log() {
console.log(msg)
}
const elTable = ref(null)
defineExpose({ elTable });
function selectElementContents(){
let range, sel;
// Ensure that range and selection are supported by the browsers
if (document.createRange && window.getSelection) {
range = document.createRange();
sel = window.getSelection();
// unselect any element in the page
sel.removeAllRanges();
try {
range.selectNodeContents(elTable.value);
sel.addRange(range);
} catch (e) {
range.selectNode(elTable.value);
sel.addRange(range);
}
document.execCommand('copy');
}
}
</script>
<template>
<h1>Hello Vue 3</h1>
<table>
<thead>
<th
v-for="ma in matable"
:key="ma.id">
{{ ma.name}}
</th>
</thead>
<tbody >
<tr>
<td v-for="ma in matable"
:key="ma.id"
v-html="ma.champ"
>
</td>
</tr>
</tbody>
</table>
<table ref="elTable" >
<tbody >
<tr >
<td v-for="ma in matable"
:key="ma.id"
v-html="ma.champ"
>
</td>
</tr>
</tbody>
</table>
<input type="button" value="Copier" ref="copy" v-on:click="selectElementContents">
</template>
<style scoped>
.visually-hidden {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
</style>