reactable icon indicating copy to clipboard operation
reactable copied to clipboard

Is it possible to set semicolon instead of comma in Reactable.downloadDataCSV as column separator

Open novotny1akub opened this issue 2 years ago • 4 comments

I would like to ask if it is possible to set semicolon instead of comma in Reactable.downloadDataCSV as a column separator. Similarly, I would like to set comma instead of dot for the decimal mark. Looking at the code of Reactable.downloadDataCSV, it does not seem to be possible. I was just wondering if I can replace Reactable.downloadDataCSV with my own function. Any help is appreciated.

novotny1akub avatar May 12 '22 07:05 novotny1akub

Neither of these are possible at this time, and I've tagged this as a feature request.

You can replace Reactable.downloadDataCSV with your own function though. Check out Reactable.getState() in the JavaScript API, which lets you get the raw table data to do whatever you want with it.

glin avatar May 14 '22 22:05 glin

Thanks a lot for steering me in the right direction Glin. For anyone trying to solve a similar issue, here is the code I used. Please note that my JavaScript is probably suboptimal though.

library(htmltools)
library(reactable)

# defining own javaScript function
# HTML function is used because of special characters such as =>
my_csv2_download <- tags$script(
  HTML(
    "
      function mydownloadDataCSV(tableId, outfName = 'data.csv', colSep = ';', decSep = ','){
        const data = Reactable.getState(tableId).data
        const headers = Object.keys(data[0]).join(colSep);
        const content = data.map(
          r => Object.values(r).map(
            c => 
              {if (typeof c === 'number') {
                return c.toString().replace('.', decSep);
              } else {
                return c;
        	}}).join(colSep)); 
        csv = [headers].concat(content).join('\\n');
        
        var blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=UTF-8;' });
        if (navigator.msSaveBlob) { // IE 10+
          navigator.msSaveBlob(blob, filename);
        } else {
          var link = document.createElement('a');
          if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute('href', url);
            link.setAttribute('download', outfName);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
          }
        }
      }
        
      "
  )
)

# self-contained example based on the standard Reactable.downloadDataCSV
htmltools::browsable(
  tagList(
    my_csv2_download, # here goes the created JS function
    tags$button("Download as CSV", onclick = "mydownloadDataCSV(tableId = 'cars-table')"),
    reactable(
      MASS::Cars93,
      defaultPageSize = 20,
      elementId = "cars-table"
    )
  )
)

novotny1akub avatar May 16 '22 13:05 novotny1akub

Just when I needed it most. Thank you @novotny1akub ! As I'm working with Portuguese characters, I have added minor changes to one line of your code:

var blob = new Blob(['\uFEFF'+csv], { type: 'text/csv;charset=utf-8;' });

It might help those with UTF-8 encoding issues (picked from here).

radovan-miletic avatar May 16 '22 16:05 radovan-miletic

Thanks a lot for pointing that out @radovan-miletic. I did not realise there was this issue. Apologies the code did not work for you 'as is'. I slightly edited my code, added some comments and also changed the encoding to utf-16 which I assumed would work for various special characters. I tried the example below for testing. Please note that this example worked with both utf-8 and utf-16.

htmltools::browsable(
  tagList(
    my_csv2_download, # here goes the created JS function
    tags$button("Download as CSV", onclick = "mydownloadDataCSV(tableId = 'cars-table')"),
    reactable(
      tibble(a = c("řeřicha", "汉字", "два")),
      defaultPageSize = 20,
      elementId = "cars-table"
    )
  )
)

novotny1akub avatar May 19 '22 12:05 novotny1akub

It's now possible to use a custom field separator and decimal separator in the development version:

  • Reactable.downloadDataCSV() in the JavaScript API now supports an additional options argument to change the field or decimal separator, include specific columns, and exclude column headers. (#239, #293)
  • New Reactable.getDataCSV() method in the JavaScript API to get the table data as a CSV string.

You can change the separators using the options argument like:

Reactable.downloadDataCSV('cars-table', 'cars93.csv', { sep: ';', dec: ',' })

There's also a new Reactable.getDataCSV() method to just get the raw CSV string, in case you want to implement your own downloader or send the CSV back to Shiny or whatever.

I didn't totally understand the encoding issues, so you can open a new issue with details if that's still a problem.

glin avatar Nov 27 '22 22:11 glin