R Shiny DT表在导出到Excel表时忽略背景颜色。

huangapple go评论67阅读模式
英文:

R shiny DT table ignoring background color while exporting to excel sheet

问题

这是您提供的代码的翻译部分:

我正在尝试从R Shiny DT表中导出数据到Excel表格,但只导出了DT表中的数据,而没有导出单元格的背景颜色。

请问是否可以帮我看一下代码需要做哪些更改?非常感谢您的帮助。

库(shiny)
库(DT)
库(htmltools)
库(colourpicker)
库(shinyWidgets)
库(DT)
库(shinythemes)

dat <- mtcars

sketch <- tags$table(
  tags$thead(
    tags$tr(
      tags$th(),
      lapply(names(dat), tags$th)
    ),
    tags$tr(
      tags$th(id = "th0"),
      tags$th(id = "th1"),
      tags$th(id = "th2"),
      tags$th(id = "th3"),
      tags$th(id = "th4"),
      tags$th(id = "th5"),
      tags$th(id = "th6"),
      tags$th(id = "th7"),
      tags$th(id = "th8"),
      tags$th(id = "th9"),
      tags$th(id = "th10"),
      tags$th(id = "th11")
    )
  )
)


js <- c(
  "function(){", 
  "  this.api().columns().every(function(i){",
  "    var column = this;",
  "    var select = $('<select multiple=\"multiple\"><option value=\"\"></option></select>')",
  "      .appendTo( $('#th'+i).empty() )", 
  "      .on('change', function(){",
  "        var vals = $('option:selected', this).map(function(index,element){",
  "          return $.fn.dataTable.util.escapeRegex($(element).val());",
  "        }).toArray().join('|');",
  "        column.search(vals.length > 0 ? '^('+vals+')$' : '', true, false).draw();",
  "      });",
  "    var data = column.data();",
  "    if(i == 0){",
  "      data.each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }else{",
  "      data.unique().sort().each(function(d, j){",
  "        select.append('<option value=\"'+d+'\">'+d+'</option>');",
  "      });",
  "    }",
  "    select.select2({width: '120%', closeOnSelect: false});",
  "  });",
  "}"
)


ca  <- c(
  "table.on('click', 'td', function(e) {",
  "  const $cell = table.cell(this).nodes().to$();",
  "  const RGB = $cell.css('background-color');",
  "  const cellColor = '#' + RGB.match(/\\d+/g).map(x => (+x).toString(16).padStart(2,0)).join``;",
  "  const selectedColor = $('#color').val().toLowerCase();",
  "  const color = cellColor == selectedColor ? '' : selectedColor;",
  "  $cell.css('background-color', color);",
  "});"
)

customize <- "
function(xlsx, button, table) {
 
  const LETTERS = 
    ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];

  var sheet = xlsx.xl.worksheets['sheet1.xml'];
 
  var row = 0;
  const num_columns = table.columns().count();
 
  $('row', sheet).each(function(x) {
    if(x > 1) {
      for(let i=0; i < num_columns; i++) {
        const $cell = $(table.cell(':eq('+row+')', i).node()); 
        const RGB = $cell.css('background-color');
        const cellColor = '#' + RGB.match(/\\d+/g).map(x => (+x).toString(16).padStart(2,0)).join``;
        if(cellColor == '#ff0000') {
          $('row:eq(' + (x) + ') c[r^=' + (LETTERS[i]) + ']', sheet).attr('s', '10');
        } else if(cellColor == '#00ff00') {
          $('row:eq(' + (x) + ') c[r^=' + (LETTERS[i]) + ']', sheet).attr('s', '15');
        }
      }
      row++;
    }
  });
}"
英文:

I am trying to export the data from R shiny DT table to the excel sheet after selecting background color to some of the cells in the DT table. But the code exports only the data from the DT table but not exporting along with the background colors selected of the cells.

Could someone please help me what changes need to be made to the code. ANy help is much appreciated.

library(shiny)
library(DT)
library(htmltools)
library(colourpicker)
library(shinyWidgets)
library(DT)
library(shinythemes)
dat &lt;- mtcars
sketch &lt;- tags$table(
tags$thead(
tags$tr(
tags$th(),
lapply(names(dat), tags$th)
),
tags$tr(
tags$th(id = &quot;th0&quot;),
tags$th(id = &quot;th1&quot;),
tags$th(id = &quot;th2&quot;),
tags$th(id = &quot;th3&quot;),
tags$th(id = &quot;th4&quot;),
tags$th(id = &quot;th5&quot;),
tags$th(id = &quot;th6&quot;),
tags$th(id = &quot;th7&quot;),
tags$th(id = &quot;th8&quot;),
tags$th(id = &quot;th9&quot;),
tags$th(id = &quot;th10&quot;),
tags$th(id = &quot;th11&quot;)
)
)
)
js &lt;- c(
&quot;function(){&quot;, 
&quot;  this.api().columns().every(function(i){&quot;,
&quot;    var column = this;&quot;,
&quot;    var select = $(&#39;&lt;select multiple=\&quot;multiple\&quot;&gt;&lt;option value=\&quot;\&quot;&gt;&lt;/option&gt;&lt;/select&gt;&#39;)&quot;,
&quot;      .appendTo( $(&#39;#th&#39;+i).empty() )&quot;, 
&quot;      .on(&#39;change&#39;, function(){&quot;,
&quot;        var vals = $(&#39;option:selected&#39;, this).map(function(index,element){&quot;,
&quot;          return $.fn.dataTable.util.escapeRegex($(element).val());&quot;,
&quot;        }).toArray().join(&#39;|&#39;);&quot;,
&quot;        column.search(vals.length &gt; 0 ? &#39;^(&#39;+vals+&#39;)$&#39; : &#39;&#39;, true, false).draw();&quot;,
&quot;      });&quot;,
&quot;    var data = column.data();&quot;,
&quot;    if(i == 0){&quot;,
&quot;      data.each(function(d, j){&quot;,
&quot;        select.append(&#39;&lt;option value=\&quot;&#39;+d+&#39;\&quot;&gt;&#39;+d+&#39;&lt;/option&gt;&#39;);&quot;,
&quot;      });&quot;,
&quot;    }else{&quot;,
&quot;      data.unique().sort().each(function(d, j){&quot;,
&quot;        select.append(&#39;&lt;option value=\&quot;&#39;+d+&#39;\&quot;&gt;&#39;+d+&#39;&lt;/option&gt;&#39;);&quot;,
&quot;      });&quot;,
&quot;    }&quot;,
&quot;    select.select2({width: &#39;120%&#39;, closeOnSelect: false});&quot;,
&quot;  });&quot;,
&quot;}&quot;)
ca  &lt;- c(
&quot;table.on(&#39;click&#39;, &#39;td&#39;, function(e) {&quot;,
&quot;  const $cell = table.cell(this).nodes().to$();&quot;,
&quot;  const RGB = $cell.css(&#39;background-color&#39;);&quot;,
&quot;  const cellColor = &#39;#&#39; + RGB.match(/\\d+/g).map(x =&gt; (+x).toString(16).padStart(2,0)).join``&quot;,
&quot;  const selectedColor = $(&#39;#color&#39;).val().toLowerCase();&quot;,
&quot;  const color = cellColor == selectedColor ? &#39;&#39; : selectedColor;&quot;,
&quot;  $cell.css(&#39;background-color&#39;, color);&quot;,
&quot;});&quot;
)
ui &lt;- fluidPage(HTML(&quot;&quot;),
tags$head(
tags$link(rel = &quot;stylesheet&quot;, href = &quot;https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css&quot;),
tags$script(src = &quot;https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js&quot;)
),
sidebarLayout(
sidebarPanel(
colourInput(
&quot;color&quot;, 
&quot;Choose background color&quot;,
palette = &quot;limited&quot;,
closeOnClick = TRUE
)
),
mainPanel(
br(),
DTOutput(&quot;dtable&quot;)
)))
server &lt;- function(input, output, session) {
output[[&quot;dtable&quot;]] &lt;- renderDT({
datatable(
dat, callback = JS(ca),  selection = &quot;none&quot;, container=sketch, editable = &quot;cell&quot;,  class = &#39;cell-border stripe&#39;, extensions = &#39;Buttons&#39;, 
options = list(dom = &#39;BPrlftip&#39;, buttons = list(&#39;copy&#39;, &#39;pdf&#39;, &#39;csv&#39;, &#39;excel&#39;, &#39;print&#39;), 
orderCellsTop = TRUE,
initComplete  = JS(js),
columnDefs = list(
list(targets = &quot;_all&quot;, className = &quot;dt-center&quot;)
)
)
)
}, server = FALSE)
}
shinyApp(ui, server)

Incorporated code

library(shiny)
library(DT)
library(htmltools)
library(colourpicker)
library(shinyWidgets)
library(DT)
library(shinythemes)
dat &lt;- mtcars
sketch &lt;- tags$table(
tags$thead(
tags$tr(
tags$th(),
lapply(names(dat), tags$th)
),
tags$tr(
tags$th(id = &quot;th0&quot;),
tags$th(id = &quot;th1&quot;),
tags$th(id = &quot;th2&quot;),
tags$th(id = &quot;th3&quot;),
tags$th(id = &quot;th4&quot;),
tags$th(id = &quot;th5&quot;),
tags$th(id = &quot;th6&quot;),
tags$th(id = &quot;th7&quot;),
tags$th(id = &quot;th8&quot;),
tags$th(id = &quot;th9&quot;),
tags$th(id = &quot;th10&quot;),
tags$th(id = &quot;th11&quot;)
)
)
)
js &lt;- c(
&quot;function(){&quot;, 
&quot;  this.api().columns().every(function(i){&quot;,
&quot;    var column = this;&quot;,
&quot;    var select = $(&#39;&lt;select multiple=\&quot;multiple\&quot;&gt;&lt;option value=\&quot;\&quot;&gt;&lt;/option&gt;&lt;/select&gt;&#39;)&quot;,
&quot;      .appendTo( $(&#39;#th&#39;+i).empty() )&quot;, 
&quot;      .on(&#39;change&#39;, function(){&quot;,
&quot;        var vals = $(&#39;option:selected&#39;, this).map(function(index,element){&quot;,
&quot;          return $.fn.dataTable.util.escapeRegex($(element).val());&quot;,
&quot;        }).toArray().join(&#39;|&#39;);&quot;,
&quot;        column.search(vals.length &gt; 0 ? &#39;^(&#39;+vals+&#39;)$&#39; : &#39;&#39;, true, false).draw();&quot;,
&quot;      });&quot;,
&quot;    var data = column.data();&quot;,
&quot;    if(i == 0){&quot;,
&quot;      data.each(function(d, j){&quot;,
&quot;        select.append(&#39;&lt;option value=\&quot;&#39;+d+&#39;\&quot;&gt;&#39;+d+&#39;&lt;/option&gt;&#39;);&quot;,
&quot;      });&quot;,
&quot;    }else{&quot;,
&quot;      data.unique().sort().each(function(d, j){&quot;,
&quot;        select.append(&#39;&lt;option value=\&quot;&#39;+d+&#39;\&quot;&gt;&#39;+d+&#39;&lt;/option&gt;&#39;);&quot;,
&quot;      });&quot;,
&quot;    }&quot;,
&quot;    select.select2({width: &#39;120%&#39;, closeOnSelect: false});&quot;,
&quot;  });&quot;,
&quot;}&quot;)
ca  &lt;- c(
&quot;table.on(&#39;click&#39;, &#39;td&#39;, function(e) {&quot;,
&quot;  const $cell = table.cell(this).nodes().to$();&quot;,
&quot;  const RGB = $cell.css(&#39;background-color&#39;);&quot;,
&quot;  const cellColor = &#39;#&#39; + RGB.match(/\\d+/g).map(x =&gt; (+x).toString(16).padStart(2,0)).join``&quot;,
&quot;  const selectedColor = $(&#39;#color&#39;).val().toLowerCase();&quot;,
&quot;  const color = cellColor == selectedColor ? &#39;&#39; : selectedColor;&quot;,
&quot;  $cell.css(&#39;background-color&#39;, color);&quot;,
&quot;});&quot;
)
customize &lt;- &quot;
function(xlsx, button, table) {
const LETTERS = 
[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;R&#39;,&#39;S&#39;,&#39;T&#39;,&#39;U&#39;,&#39;V&#39;,&#39;W&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;];
var sheet = xlsx.xl.worksheets[&#39;sheet1.xml&#39;];
var row = 0;
const num_columns = table.columns().count();
$(&#39;row&#39;, sheet).each(function(x) {
if(x &gt; 1) {
for(let i=0; i &lt; num_columns; i++) {
const $cell = $(table.cell(&#39;:eq(&#39;+row+&#39;)&#39;, i).node()); 
const RGB = $cell.css(&#39;background-color&#39;);
const cellColor = &#39;#&#39; + RGB.match(/\\d+/g).map(x =&gt; (+x).toString(16).padStart(2,0)).join``;
if(cellColor == &#39;#ff0000&#39;) {
$(&#39;row:eq(&#39; + (x) + &#39;) c[r^=&#39; + (LETTERS[i]) + &#39;]&#39;, sheet).attr(&#39;s&#39;, &#39;10&#39;);
} else if(cellColor == &#39;#00ff00&#39;) {
$(&#39;row:eq(&#39; + (x) + &#39;) c[r^=&#39; + (LETTERS[i]) + &#39;]&#39;, sheet).attr(&#39;s&#39;, &#39;15&#39;);
}
}
row++;
}
});
}&quot;
ui &lt;- fluidPage(HTML(&quot;&quot;),
tags$head(
tags$link(rel = &quot;stylesheet&quot;, href = &quot;https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css&quot;),
tags$script(src = &quot;https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js&quot;)
),
sidebarLayout(
sidebarPanel(
colourInput(
&quot;color&quot;, 
&quot;Choose background color&quot;,
palette = &quot;limited&quot;,
closeOnClick = TRUE
)
),
mainPanel(
br(),
DTOutput(&quot;dtable&quot;)
)))
server &lt;- function(input, output, session) {
output[[&quot;dtable&quot;]] &lt;- renderDT({
datatable(
dat, callback = JS(ca),  selection = &quot;none&quot;, container=sketch, editable = &quot;cell&quot;,  class = &#39;cell-border stripe&#39;, extensions = &#39;Buttons&#39;, 
options = list(dom = &#39;BPrlftip&#39;, buttons = list(list(
extend = &quot;excel&quot;,
text = &quot;Save XLSX&quot;,
customize = JS(customize))), 
orderCellsTop = TRUE,
initComplete  = JS(js),
columnDefs = list(
list(targets = &quot;_all&quot;, className = &quot;dt-center&quot;)
)))
}, server = FALSE)
}
shinyApp(ui, server)

答案1

得分: 1

以下是您提供的代码的中文翻译部分:

必须使用Excel按钮的“customize”选项。这有点让人烦恼,因为每种颜色都对应一个特殊的Excel代码,我们必须列出所有可能性。在这里,我开始为红色和绿色实现它。

library(shiny)
library(DT)
library(colourpicker)

callback <- c(
  "table.on('click', 'td', function(e) {",
  "  const $cell = table.cell(this).nodes().to$();",
  "  const RGB = $cell.css('background-color');",
  "  const cellColor = '#' + RGB.match(/\\d+/g).map(x => (+x).toString(16).padStart(2,0)).join``;",
  "  const selectedColor = $('#color').val().toLowerCase();",
  "  const color = cellColor == selectedColor ? '' : selectedColor;",
  "  $cell.css('background-color', color);",
  "});"
)

customize <- "
function(xlsx, button, table) {
 
  const LETTERS = 
    ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];

  var sheet = xlsx.xl.worksheets['sheet1.xml'];
 
  var row = 0;
  const num_columns = table.columns().count();
 
  $('row', sheet).each(function(x) {
    if(x > 1) {
      for(let i=0; i < num_columns; i++) {
        const $cell = $(table.cell(':eq('+row+')', i).node()); 
        const RGB = $cell.css('background-color');
        const cellColor = '#' + RGB.match(/\\d+/g).map(x => (+x).toString(16).padStart(2,0)).join``;
        if(cellColor == '#ff0000') {
          $('row:eq(' + (x) + ') c[r^=' + (LETTERS[i]) + ']', sheet).attr('s', '10');
        } else if(cellColor == '#00ff00') {
          $('row:eq(' + (x) + ') c[r^=' + (LETTERS[i]) + ']', sheet).attr('s', '15');
        }
      }
      row++;
    }
  });
}"

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      colourInput(
        "color", 
        "选择背景颜色",
        palette = "limited",
        closeOnClick = TRUE
      )
    ),
    mainPanel(
      br(),
      DTOutput("dtable")
    )
  )
)

server <- function(input, output, session) {
  
  output[["dtable"]] <- renderDT({
    datatable(
      iris, 
      extensions = "Buttons",
      selection = "none",
      callback = JS(callback),
      options = list(
        dom = "Bfrtip",
        buttons = list(
          list(
            extend = "excel",
            text = "保存 XLSX",
            customize = JS(customize)
          )
        )
      )
    )
  })
}

shinyApp(ui, server)
英文:

One has to use the customize option of the Excel button. That's a bit annoying, because each color corresponds to a special Excel code and we would have to list all possibilities. Here I started to implement it for red and green only.

library(shiny)
library(DT)
library(colourpicker)

callback &lt;- c(
  &quot;table.on(&#39;click&#39;, &#39;td&#39;, function(e) {&quot;,
  &quot;  const $cell = table.cell(this).nodes().to$();&quot;,
  &quot;  const RGB = $cell.css(&#39;background-color&#39;);&quot;,
  &quot;  const cellColor = &#39;#&#39; + RGB.match(/\\d+/g).map(x =&gt; (+x).toString(16).padStart(2,0)).join``&quot;,
  &quot;  const selectedColor = $(&#39;#color&#39;).val().toLowerCase();&quot;,
  &quot;  const color = cellColor == selectedColor ? &#39;&#39; : selectedColor;&quot;,
  &quot;  $cell.css(&#39;background-color&#39;, color);&quot;,
  &quot;});&quot;
)


customize &lt;- &quot;
function(xlsx, button, table) {
 
  const LETTERS = 
    [&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;R&#39;,&#39;S&#39;,&#39;T&#39;,&#39;U&#39;,&#39;V&#39;,&#39;W&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;];

  var sheet = xlsx.xl.worksheets[&#39;sheet1.xml&#39;];
 
  var row = 0;
  const num_columns = table.columns().count();
 
  $(&#39;row&#39;, sheet).each(function(x) {
    if(x &gt; 1) {
      for(let i=0; i &lt; num_columns; i++) {
        const $cell = $(table.cell(&#39;:eq(&#39;+row+&#39;)&#39;, i).node()); 
        const RGB = $cell.css(&#39;background-color&#39;);
        const cellColor = &#39;#&#39; + RGB.match(/\\d+/g).map(x =&gt; (+x).toString(16).padStart(2,0)).join``;
        if(cellColor == &#39;#ff0000&#39;) {
          $(&#39;row:eq(&#39; + (x) + &#39;) c[r^=&#39; + (LETTERS[i]) + &#39;]&#39;, sheet).attr(&#39;s&#39;, &#39;10&#39;);
        } else if(cellColor == &#39;#00ff00&#39;) {
          $(&#39;row:eq(&#39; + (x) + &#39;) c[r^=&#39; + (LETTERS[i]) + &#39;]&#39;, sheet).attr(&#39;s&#39;, &#39;15&#39;);
        }
      }
      row++;
    }
  });
}&quot;
  

ui &lt;- fluidPage(
  sidebarLayout(
    sidebarPanel(
      colourInput(
        &quot;color&quot;, 
        &quot;Choose background color&quot;,
        palette = &quot;limited&quot;,
        closeOnClick = TRUE
      )
    ),
    mainPanel(
      br(),
      DTOutput(&quot;dtable&quot;)
    )
  )
)

server &lt;- function(input, output, session) {
  
  output[[&quot;dtable&quot;]] &lt;- renderDT({
    datatable(
      iris, 
      extensions = &quot;Buttons&quot;,
      selection = &quot;none&quot;,
      callback = JS(callback),
      options = list(
        dom = &quot;Bfrtip&quot;,
        buttons = list(
          list(
            extend = &quot;excel&quot;,
            text = &quot;Save XLSX&quot;,
            customize = JS(customize)
          )
        )
      )
    )
  })
}

shinyApp(ui, server)

R Shiny DT表在导出到Excel表时忽略背景颜色。

huangapple
  • 本文由 发表于 2023年6月29日 16:45:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579460.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定