Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
novotny1akub opened this issue May 12, 2022 · 5 comments
Labels
enhancement New feature or request
Milestone

Comments

@novotny1akub
Copy link

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.

@glin glin added the enhancement New feature or request label May 14, 2022
@glin
Copy link
Owner

glin commented May 14, 2022

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.

@novotny1akub
Copy link
Author

novotny1akub commented May 16, 2022

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-16;' });
        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"
    )
  )
)

@radovan-miletic
Copy link

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).

@novotny1akub
Copy link
Author

novotny1akub commented May 19, 2022

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"
    )
  )
)

@glin
Copy link
Owner

glin commented Nov 27, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants