1

我编写了一个脚本,定期从 2 个数据库中提取和汇总数据。我write.xlsx用来将 3 个数据框写入 3 个不同的选项卡:

  • Tab1 是来自一个数据库的数据,
  • Tab2 是来自另一个的数据,并且
  • Tab3 是两者汇总的数据。

如果每次运行都覆盖选项卡 1 和 2 很好,但我希望 Tab3 每次运行都添加一个新行(sys.date在 col1 中),从而为我提供数据摘要的历史记录。这可能吗?如何?

append=TRUE没有得到我想要的东西。我的下一个选择(不太理想)是将汇总数据写入文件名中带有 sys.date 的单独文件。

# Write to spreadsheet w/ 3 tabs
write.xlsx(df1, file = "file_location\\filename.xlsx", sheetName = "dataset1", row.names = FALSE, append = FALSE) #write to tab1

write.xlsx(df2, file = "file_location\\filename.xlsx", sheetName = "dataset2", row.names = FALSE, append = TRUE) #write to tab2

write.xlsx(summary_df, file = "file_location\\filename.xlsx", sheetName = "summarized_data", row.names = FALSE, append = TRUE) #write to next blank row in tab3

该脚本会在每次运行时覆盖汇总数据。我希望它将它附加到下一个空白行。

4

2 回答 2

1

因此,该openxlsx包不仅允许您指定要附加新数据的行,还允许您提取当前工作簿工作表的最后一行。诀窍是将日期和新的摘要数据写为包DataTable独有的对象openxlsx。该函数writeDataTable将允许您执行此操作,唯一需要的参数是工作簿对象的名称、工作簿中工作表的名称和任何 Rdata.frame对象。可以使用loadWorkbook简单地获取 Excel 文件名路径的函数来获取工作簿对象。您还可以阅读具有多个工作表的整个 Excel 工作簿,然后提取和修改各个工作表,然后再将它们保存回原始 Excel 工作簿。

要创建初始工作簿以使更新与原始工作簿兼容,只需将write.xlsx语句替换writeDataTable为如下语句:

    library(openxlsx)
    wb <- createWorkbook()
    writeDataTable(wb,sheet="dataset1",x=dataset1)
    writeDataTable(wb,sheet="dataset2",x=dataset2)
    writeDataTable(wb,sheet="summarized_dat",x=summary_df)
    saveWorkbook(wb,"file_location\\filename.xlsx")

因此,在创建初始工作簿之后,您现在可以简单地加载它并单独修改工作表。既然你提到你可以覆盖 dataset1 和 dataset2 我将专注于 summary_dat 因为你可以使用上面的代码来覆盖以前的数据集:

    library(openxlsx)
    wb <- loadWorkbook("file_location\\filename.xlsx")

现在您可以使用下面的函数将新的汇总数据附加到日期中。为此,我将日期转换为data.frame对象,但您也可以使用该writeData函数。我喜欢这个writeDataTable功能,因为您可以使用getTables它更轻松地提取最后一行。getTables使用我的一个工作簿作为示例,调用的输出如下所示,其中三个表垂直堆叠:

    [1] "A1:P61"   "A62:A63"  "A64:T124"

诀窍是提取最后一行编号,在本例中为 124。所以这是我刚刚快速编写的一个函数,它将自动为您完成所有这些操作,并获取一个工作簿对象,您希望修改的工作表的名称,并将更新的汇总表保存为data.frame对象:

    Update_wb_fun<-function(wb, sheetname, newdata){

        tmp_wb <- wb #creates copy if you wish to keep the original before modifying as a check

        table_cells <- names(getTables(tmp_wb,sheetname)) #Extracts the Excel cells for all DataTables in the worksheet. First run there will only be one but in subsequent runs there will be more and you will want the last one.

        lastrow <- as.numeric(gsub("[A-z]","",unlist(strsplit(table_cells[length(table_cells)],":"))[2])) #Extracts the last row

        start_time_row <- lastrow+1

        writeDataTable(tmp_wb,sheet=sheetname,x=data.frame(Sys.Date()),startRow = start_time_row) #Appending the time stamp as DatTable.

        writeDataTable(tmp_wb,sheet=sheetname,x=newdata,startRow = start_time_row+2) #Appending the new data under the time stamp

        return(tmp_wb)
    }

提取“lastrow”的代码看起来有点复杂,但使用基本 R 函数来提取该行号。该length函数从上面的示例输出中提取最后一个元素(例如,“A64:T124”)。用strsplit冒号分隔字符串,我们必须unlist为此创建一个向量并获得第二个元素(例如,“T124”)。最后gsub删除字母并只保留行号(例如,“124”)。从as.numeric字符对象转换为数字对象。

因此,要调用此函数并更新“summarized_dat”工作表,请执行以下操作:

    test_wb <- Update_wb_fun(wb, "summarized_dat", summary_df) #Here I am preserving the original workbook object before modification but you could save to wb directly.

    saveWorkbook(test_wb, "file_location\\filename.xlsx", overWrite=T) #Need to use the overWrite option if filename already exists.

这就是您可以附加到“summarized_dat”表的方式。writeDataTable在最终保存之前,您还可以通过在我们编写函数之前重新运行语句来更新前两张表。让我知道这是否正是您要查找的内容,我可以轻松修改此代码。祝你好运!

于 2019-01-18T03:18:48.087 回答
0

我会查看 openxlsx 包 - 它允许您从 Excel 文件中的给定行开始写入数据。唯一需要注意的是,您需要读取当前 Excel 文件以确定哪一行是包含数据的最后一行。您可以使用 readxl 包并使用从 Excel 文件创建的数据框的 nrow() 来确定行数。

于 2019-01-17T20:59:31.443 回答