R Shiny DT新增行时自动生成递增Reference.Number方法
实现方案
核心调整点:将表格数据改为响应式存储,每次点击添加按钮前先计算当前表格内参考编号的最大值,自动生成递增的新编号填入新行,再同步更新表格和存储的数据,避免编号重复、断号问题。
具体修改逻辑
- 把初始静态数据集改为响应式值存储,实时同步用户新增、编辑后的最新表格内容,避免无法获取修改后数据的问题
- 废弃提前写死的空行模板,每次触发添加动作时,实时读取当前表格的
Reference.Number列,转成数值后取最大值加1,生成新的连续参考编号 - 新增行后同步更新响应式存储的表格数据,保证下一次点击添加时,计算最大值的数据源是最新状态
- 补充单元格编辑同步逻辑,避免用户手动修改已有参考编号后,新生成的编号出现冲突
修改后可直接运行的完整代码
library(shiny) library(shinythemes) library(shinyWidgets) library(shinyanimate) library(DT) library(tidyverse) # 初始示例数据 df <- structure(list(Reference.Number = c("33331", "33332", "33333", "33334", "33335"), Request.Date = c("1/6/2022", "1/6/2022", "1/19/2022", "1/20/2021", "1/24/2022"), Requestor.Name = c("Comm Dist 3 by Kitty", "Comm Dist 3 by Kitty", "Updated maps for David", " Stone Cold", "Updated SOE 60 inch wall map"), Requestor.Dept.Div = c("C 3 Staff", "C 3 Staff", "Unincorp & Comm", "Mt.Rushmore AME Church Ft. Billy", "SOE"), Requestor.Phone = c("", "", "", "", ""), Contact.Person = c("Tommy", "Tommy", "Bob", "Bob", "Joe"), Contact.Phone = c("1111", "2222", "3333", "ext 1111", "3434"), Deadline = c("1/20/2022", "1/20/2022", "1/22/2022", "", "1/24/2022"), Project.Description = c("45x36 portrait map ", "45x36 portrait map ", "24x24 Unincorporated areas", "Percent Females Aged 25 - 55 Below Poverty Level By Zip Code", "SOE Wall Map 60x60 p"), Project.File.Location = c("", "", "C:\\ABC\\Tommy\\work|Map-Projects\\BD Unincororated\\#14785 Unincorporated 24x24.pdf", "C:\\ABC\\Demographics\\Demographic_Request\\FemalesAge10-18BelowPoveryLevel\\FemalesAge10-18BelowPoveryLevel.aprx", "C:\\ABC\\Tommy\\work|Map-Projects\\BD Unincororated\\#14786 V P 60x60.pdf" ), PDF.File.....Map.Name.... = c("", "", "", "C:\\ABC\\Demographics\\Demographic_Request\\FemalesAge10-18BelowPoveryLevel\\pdfs\\MapNo14785.pdf", ""), Assigned.To = c("", "", "", "", ""), Completion.Date = c("", "", "", "", ""), Notes = c(NA, NA, NA, NA, NA), Year = c(2022, 2022, 2022, 2022, 2022)), class = "data.frame", row.names = c(NA, -5L)) # UI部分保持原有逻辑不变 ui = navbarPage(tags$style("table, .table {color: unset;} .dataTable th, .datatables input {color: white}"), title = div("GIS Team Projects"), theme = shinytheme("cyborg"), tabPanel("GIS Projects", icon = icon("info"), div(p(h1("Instructions:"),style="text-align: justify;")), p("1. The user can add their project details.", style="color:black"), uiOutput("all"), sidebarLayout( sidebarPanel( actionButton("addData", "Add Project Details"), ), mainPanel( downloadButton("download1","Download data as csv"), DTOutput("contents")),) ) ) server <- function(input, output) { # 用响应值存储表格全量数据,实时同步最新状态 rv <- reactiveValues( table_data = df ) # 渲染可编辑表格 output$contents = renderDT({ rv$table_data }, server = FALSE, editable = TRUE, options = list(lengthChange = TRUE), rownames = FALSE) # 创建表格代理对象 proxy = dataTableProxy(outputId = "contents") # 监听添加按钮点击事件 observeEvent(input$addData, { # 提取当前所有参考编号,转数值后取最大值 current_max_ref <- max(as.numeric(rv$table_data$Reference.Number), na.rm = TRUE) # 生成下一个连续编号,保持字符型和原格式一致 new_ref_num <- as.character(current_max_ref + 1) # 生成新空行,仅填充参考编号,其余字段为空 new_row <- rv$table_data[1, ] new_row[1, ] <- NA new_row$Reference.Number <- new_ref_num # 统一字符型字段空值格式,和原表保持一致 new_row <- new_row %>% mutate(across(where(is.character), ~ifelse(is.na(.), "", .))) # 向表格添加新行 proxy %>% addRow(new_row) # 同步更新响应值里的表格数据,保证下一次计算编号使用最新数据 rv$table_data <- rbind(rv$table_data, new_row) }) # 同步单元格编辑内容到响应值,避免手动修改编号后新编号生成错误 observeEvent(input$contents_cell_edit, { edit_info <- input$contents_cell_edit rv$table_data[edit_info$row, edit_info$col] <- edit_info$value }) # 补全原代码缺失的下载功能逻辑 output$download1 <- downloadHandler( filename = function() { paste0("GIS_project_records_", Sys.Date(), ".csv") }, content = function(file) { write.csv(rv$table_data, file, row.names = FALSE, fileEncoding = "UTF-8") } ) } # 启动应用 shinyApp(ui = ui, server = server)
补充说明
如果后续参考编号需要增加前缀(比如PROJ-33335这类格式),只需要调整编号提取、拼接的规则即可,核心的响应式存储数据、实时计算最大值的逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

