read.xlsx cannot find Excel file - r

I want to read a bunch of excel files all located in the same directory and store them in different sheets in a consolidated Excel file.
I initially tried using XLConnect but kept getting the error GC overhead limit exceeded. I stumbled upon this question which says that it is a common problem with Java based Excel handling packages such as XLConnect and xlsx. I tried the memory management trick suggested there, but it did not work. One of the comments in one of the comments on the accepted answers suggested using openxls as it based on RCpp and hence avoid this particular problem.
My current code is as follows:
library(openxlsx)
mnth="January"
files <- list.files(path="./Original Files", pattern=mnth, full.names=T, recursive=FALSE) #pattern match as multiple files are from the same month
# Read them into a list and write to sheet
wb <- createWorkbook()
lapply(files, function(x){
print(x)
xlFile<-read.xlsx(xlsxFile = x, sheet = 1, startRow = 2, colNames = T) #Also tried
str(xlFile)
#Create a sheet in the new Excel file called Consolidated.xlsx with the month name
#Append current data in sheet
})
The problem I am getting is the error: Error in read.xlsx.default(xlsxFile = x, sheet = 1, startRow = 2, colNames = T) : openxlsx can not read .xls or .xlm files!
I have ensured that files variable contains all the files of interest (Ex: January 2015.xls, January 2016.xls, etc). I have also ensured that the path to the file is correct and the Excel files actually exists there.
I have left the writing to Excel as skeleton code as I need to solve the problem with reading the files first.
In case it helps, here is the code attempt with XLConnect
library(XLConnect)
setwd("D:/something/something")
mnth="January"
files <- list.files(path="./Original Files", pattern=mnth, full.names=T, recursive=FALSE)
# Read them into a list
df.list = lapply(files, readWorksheetFromFile, sheet=1, startRow=2)
#combine them into a single data frame and write to disk:
df = do.call(rbind, df.list)
rm(df.list)
outputFileName<-"Consolidated.xlsx"
# Load workbook (create if not existing)
wb <- loadWorkbook(outputFileName, create = TRUE)
createSheet(wb, name = mnth)
writeWorksheet(wb,df,sheet = mnth)
#write.xlsx2(df, outputFileName, sheetName = mnth, col.names = T, row.names = F, append = TRUE)
saveWorkbook(wb)
rm(df)
gc()

Related

Select specific data frames from global environment [duplicate]

I am surprised to find that there is no easy way to export multiple data.frame to multiple worksheets of an Excel file? I tried xlsx package, seems it can only write to one sheet (override old sheet); I also tried WriteXLS package, but it gives me error all the time...
My code structure is like this: by design, for each iteration, the output dataframe (tempTable) and the sheetName (sn) got updated and exported into one tab.
for (i in 2 : ncol(code)){
...
tempTable <- ...
sn <- ...
WriteXLS("tempTable", ExcelFileName = "C:/R_code/../file.xlsx",
SheetNames = sn);
}
I can export to several cvs files, but there has to be an easy way to do that in Excel, right?
You can write to multiple sheets with the xlsx package. You just need to use a different sheetName for each data frame and you need to add append=TRUE:
library(xlsx)
write.xlsx(dataframe1, file="filename.xlsx", sheetName="sheet1", row.names=FALSE)
write.xlsx(dataframe2, file="filename.xlsx", sheetName="sheet2", append=TRUE, row.names=FALSE)
Another option, one that gives you more control over formatting and where the data frame is placed, is to do everything within R/xlsx code and then save the workbook at the end. For example:
wb = createWorkbook()
sheet = createSheet(wb, "Sheet 1")
addDataFrame(dataframe1, sheet=sheet, startColumn=1, row.names=FALSE)
addDataFrame(dataframe2, sheet=sheet, startColumn=10, row.names=FALSE)
sheet = createSheet(wb, "Sheet 2")
addDataFrame(dataframe3, sheet=sheet, startColumn=1, row.names=FALSE)
saveWorkbook(wb, "My_File.xlsx")
In case you might find it useful, here are some interesting helper functions that make it easier to add formatting, metadata, and other features to spreadsheets using xlsx:
http://www.sthda.com/english/wiki/r2excel-read-write-and-format-easily-excel-files-using-r-software
You can also use the openxlsx library to export multiple datasets to multiple sheets in a single workbook.The advantage of openxlsx over xlsx is that openxlsx removes the dependencies on java libraries.
Write a list of data.frames to individual worksheets using list names as worksheet names.
require(openxlsx)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2)
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")
There's a new library in town, from rOpenSci: writexl
Portable, light-weight data frame to xlsx exporter based on
libxlsxwriter. No Java or Excel required
I found it better and faster than the above suggestions (working with the dev version):
library(writexl)
sheets <- list("sheet1Name" = sheet1, "sheet2Name" = sheet2) #assume sheet1 and sheet2 are data frames
write_xlsx(sheets, "path/to/location")
Many good answers here, but some of them are a little dated. If you want to add further worksheets to a single file then this is the approach I find works for me. For clarity, here is the workflow for openxlsx version 4.0
# Create a blank workbook
OUT <- createWorkbook()
# Add some sheets to the workbook
addWorksheet(OUT, "Sheet 1 Name")
addWorksheet(OUT, "Sheet 2 Name")
# Write the data to the sheets
writeData(OUT, sheet = "Sheet 1 Name", x = dataframe1)
writeData(OUT, sheet = "Sheet 2 Name", x = dataframe2)
# Export the file
saveWorkbook(OUT, "My output file.xlsx")
EDIT
I've now trialled a few other answers, and I actually really like #Syed's. It doesn't exploit all the functionality of openxlsx but if you want a quick-and-easy export method then that's probably the most straightforward.
I'm not familiar with the package WriteXLS; I generally use XLConnect:
library(XLConnect)
##
newWB <- loadWorkbook(
filename="F:/TempDir/tempwb.xlsx",
create=TRUE)
##
for(i in 1:10){
wsName <- paste0("newsheet",i)
createSheet(
newWB,
name=wsName)
##
writeWorksheet(
newWB,
data=data.frame(
X=1:10,
Dataframe=paste0("DF ",i)),
sheet=wsName,
header=TRUE,
rownames=NULL)
}
saveWorkbook(newWB)
This can certainly be vectorized, as #joran noted above, but just for the sake of generating dynamic sheet names quickly, I used a for loop to demonstrate.
I used the create=TRUE argument in loadWorkbook since I was creating a new .xlsx file, but if your file already exists then you don't have to specify this, as the default value is FALSE.
Here are a few screenshots of the created workbook:
Incase data size is small, R has many packages and functions which can be utilized as per your requirement.
write.xlsx, write.xlsx2, XLconnect also do the work but these are sometimes slow as compare to openxlsx.
So, if you are dealing with the large data sets and came across java errors. I would suggest to have a look of "openxlsx" which is really awesome and reduce the time to 1/12th.
I've tested all and finally i was really impressed with the performance of openxlsx capabilities.
Here are the steps for writing multiple datasets into multiple sheets.
install.packages("openxlsx")
library("openxlsx")
start.time <- Sys.time()
# Creating large data frame
x <- as.data.frame(matrix(1:4000000,200000,20))
y <- as.data.frame(matrix(1:4000000,200000,20))
z <- as.data.frame(matrix(1:4000000,200000,20))
# Creating a workbook
wb <- createWorkbook("Example.xlsx")
Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") ## path to zip.exe
Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") has to be static as it takes reference of some utility from Rtools.
Note: Incase Rtools is not installed on your system, please install it first for smooth experience. here is the link for your reference: (choose appropriate version)
https://cran.r-project.org/bin/windows/Rtools/
check the options as per link below (need to select all the check box while installation)
https://cloud.githubusercontent.com/assets/7400673/12230758/99fb2202-b8a6-11e5-82e6-836159440831.png
# Adding a worksheets : parameters for addWorksheet are 1. Workbook Name 2. Sheet Name
addWorksheet(wb, "Sheet 1")
addWorksheet(wb, "Sheet 2")
addWorksheet(wb, "Sheet 3")
# Writing data in to respetive sheets: parameters for writeData are 1. Workbook Name 2. Sheet index/ sheet name 3. dataframe name
writeData(wb, 1, x)
# incase you would like to write sheet with filter available for ease of access you can pass the parameter withFilter = TRUE in writeData function.
writeData(wb, 2, x = y, withFilter = TRUE)
## Similarly writeDataTable is another way for representing your data with table formatting:
writeDataTable(wb, 3, z)
saveWorkbook(wb, file = "Example.xlsx", overwrite = TRUE)
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken
openxlsx package is really good for reading and writing huge data from/ in excel files and has lots of options for custom formatting within excel.
The interesting fact is that we dont have to bother about java heap memory here.
I had this exact problem and I solved it this way:
library(openxlsx) # loads library and doesn't require Java installed
your_df_list <- c("df1", "df2", ..., "dfn")
for(name in your_df_list){
write.xlsx(x = get(name),
file = "your_spreadsheet_name.xlsx",
sheetName = name)
}
That way you won't have to create a very long list manually if you have tons of dataframes to write to Excel.
I regularly use the packaged rio for exporting of all kinds. Using rio, you can input a list, naming each tab and specifying the dataset. rio compiles other in/out packages, and for export to Excel, uses openxlsx.
library(rio)
filename <- "C:/R_code/../file.xlsx"
export(list(sn1 = tempTable1, sn2 = tempTable2, sn3 = tempTable3), filename)
tidy way of taking one dataframe and writing sheets by groups:
library(tidyverse)
library(xlsx)
mtcars %>%
mutate(cyl1 = cyl) %>%
group_by(cyl1) %>%
nest() %>%
ungroup() %>%
mutate(rn = row_number(),
app = rn != 1,
q = pmap(list(rn,data,app),~write.xlsx(..2,"test1.xlsx",as.character(..1),append = ..3)))
For me, WriteXLS provides the functionality you are looking for. Since you did not specify which errors it returns, I show you an example:
Example
library(WriteXLS)
x <- list(sheet_a = data.frame(a=letters), sheet_b = data.frame(b = LETTERS))
WriteXLS(x, "test.xlsx", names(x))
Explanation
If x is:
a list of data frames, each one is written to a single sheet
a character vector (of R objects), each object is written to a single sheet
something else, then see also what the help states:
More on usage
?WriteXLS
shows:
`x`: A character vector or factor containing the names of one or
more R data frames; A character vector or factor containing
the name of a single list which contains one or more R data
frames; a single list object of one or more data frames; a
single data frame object.
Solution
For your example, you would need to collect all data.frames in a list during the loop, and use WriteXLS after the loop has finished.
Session info
R 3.2.4
WriteXLS 4.0.0
I do it in this way for openxlsx using following function
mywritexlsx<-function(fname="temp.xlsx",sheetname="Sheet1",data,
startCol = 1, startRow = 1, colNames = TRUE, rowNames = FALSE)
{
if(! file.exists(fname))
wb = createWorkbook()
else
wb <- loadWorkbook(file =fname)
sheet = addWorksheet(wb, sheetname)
writeData(wb,sheet,data,startCol = startCol, startRow = startRow,
colNames = colNames, rowNames = rowNames)
saveWorkbook(wb, fname,overwrite = TRUE)
}
I do this all the time, all I do is
WriteXLS::WriteXLS(
all.dataframes,
ExcelFileName = xl.filename,
AdjWidth = T,
AutoFilter = T,
FreezeRow = 1,
FreezeCol = 2,
BoldHeaderRow = T,
verbose = F,
na = '0'
)
and all those data frames come from here
all.dataframes <- vector()
for (obj.iter in all.objects) {
obj.name <- obj.iter
obj.iter <- get(obj.iter)
if (class(obj.iter) == 'data.frame') {
all.dataframes <- c(all.dataframes, obj.name)
}
obviously sapply routine would be better here
for a lapply-friendly version..
library(data.table)
library(xlsx)
path2txtlist <- your.list.of.txt.files
wb <- createWorkbook()
lapply(seq_along(path2txtlist), function (j) {
sheet <- createSheet(wb, paste("sheetname", j))
addDataFrame(fread(path2txtlist[j]), sheet=sheet, startColumn=1, row.names=FALSE)
})
saveWorkbook(wb, "My_File.xlsx")

How do I get the file path of a file saved using write.xlsx or another function in R?

I am creating two dataframes and one graph on Rstudio. I wrote code to transfer them to an Excel file on different sheets, but each time I have to choose the file path using file.choose(). Is it possible to assign the file path to the variable when saving the file for the first time? If such a method exists, how can it be done?
I would also like to receive comments on how to more easily export my dataframes to an excel file. I shared my codes.
Thank you to everyone.
dataframe1 <- data.frame("A"=1, "B"=2)
dataframe2 <- data.frame("C"=3,"D"=4)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2, )
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")
dflist <- list("Sonuçlar"=yazılacakdosya0, "Frame"=dtf, "Grafik"="")
edc <- write.xlsx(dflist, file.choose(new = T), colNames = TRUE,
borders = "surrounding",
firstRow = T,
headerStyle = hs)
require(ggplot2)
q1 <- qplot(hist(yazılacakdosya0$Puan))
print(q1)
insertPlot(wb=edc, sheet = "Grafik")
saveWorkbook(edc, file = file.choose(), overwrite = T)
Just save the file path before you call saveWorkbook
file = file.choose()
saveWorkbook(edc, file = file, overwrite = T)

How do I apply the same action to all Excel Files in the directory?

I need to shape the data stored in Excel files and save it as new .csv files. I figured out what specific actions should be done, but can't understand how to use lapply.
All Excell files have the same structure. Each of the .csv files should have the name of original files.
## the original actions successfully performed on a single file
library(readxl)
library("reshape2")
DataSource <- read_excel("File1.xlsx", sheet = "Sheet10")
DataShaped <- melt(subset(DataSource [-(1),], select = - c(ng)), id.vars = c ("itemname","week"))
write.csv2(DataShaped, "C:/Users/Ol/Desktop/Meta/File1.csv")
## my attempt to apply to the rest of the files in the directory
lapply(Files, function (i){write.csv2((melt(subset(read_excel(i,sheet = "Sheet10")[-(1),], select = - c(ng)), id.vars = c ("itemname","week"))))})
R returns the result to the console but doesn't create any files. The result resembles .csv structure.
Could anybody explain what I am doing wrong? I'm new to R, I would be really grateful for the help
Answer
Thanks to the prompt answer from #Parfait the code is working! So glad. Here it is:
library(readxl)
library(reshape2)
Files <- list.files(full.names = TRUE)
lapply(Files, function(i) {
write.csv2(
melt(subset(read_excel(i, sheet = "Decomp_Val")[-(1),],
select = -c(ng)),id.vars = c("itemname","week")),
file = paste0(sub(".xlsx", ".csv",i)))
})
It reads an Excel file in the directory, drops first row (but headers) and the column named "ng", melts the data by labels "itemname" and "week", writes the result as a .csv to the working directory attributing the name of the original file. And then - rinse and repeat.
Simply pass an actual file path to write.csv2. Otherwise, as denoted in docs ?write.csv, the default value for file argument is empty string "" :
file: either a character string naming a file or a connection open for writing. "" indicates output to the console.
Below concatenates the Excel file stem to the specified path directory with .csv extension:
path <- "C:/Users/Ol/Desktop/Meta/"
lapply(Files, function (i){
write.csv2(
melt(subset(read_excel(i, sheet = "Sheet10")[-(1),],
select = -c(ng)),
id.vars = c("itemname","week")),
file = paste0(path, sub(".xlsx", ".csv", i))
)
})

Reading Excel files with XLConnect returns "Error: InvalidFormatException (Java): Your InputStream was neither an OLE2 stream, nor an OOXML stream"

I am trying to read the contents of a score of Excel files into R with XLConnect. This is a simplified version of my code:
# point to a folder
path <- "/path/to/folder"
# get all the Excel files in that folder
files <- list.files(path, pattern = "*.xlsx")
# create an empty data frame
dat <- data.frame(var.1 = character(), var.2 = numeric())
# load XLConnect
library("XLConnect")
# loop over the files
for (i in seq_along(files)) {
# read each Excel file
wb <- loadWorkbook(paste(pfad, files[i], sep = "/"))
# fill the data frame with data from the Excel file
dat[i, 1:2] <- readWorksheet(wb, "Table1", startRow = 1, startCol = 1, endRow = 2, endCol = 1, header = FALSE)
rm(wb)
}
I can read in a single file when I specify it with loadWorkbook(paste(pfad, files[1], sep = "/")), but when I loop over the file list with files[i], the code inside the for-loop returns the following error:
Error: InvalidFormatException (Java):
Your InputStream was neither an OLE2 stream, nor an OOXML stream
What am I doing wrong?
The problem had nothing to do with my code.
I had some of the files in that folder open in Excel. When you open a file in Excel, Excel creates an invisible file named "~$filename.xlsx". Since my regular expression searched for files with the suffix ".xlsx", these files were found, too, and since these files are not spreadsheet files, XLConnect couldn't read them and threw an error.
I solved the problem by closing those files in Excel.
Another solution would be to exclude files that begin with a tilde in the regular expression, with something like:
list.files(path, pattern = "^[^~].+\\.xlsx")

openxlsx::write.xlsx throwing unused argument error for startRow

I want to read a bunch of excel files all located in the same directory and store them in different sheets in a consolidated Excel file.
I am using a combination of xlsx and openxlsx to achieve this. The reason is, openxlsx can not read .xls file and xlsx is java based and runs out of memory throwing GC overhead limit exceeded error when trying to write large files.
Here is the code I am using:
library(openxlsx)
library(xlsx)
mnth="january"
outputFileName<-"Consolidated.xlsx"
files <- list.files(path="./Original Files", pattern=mnth, full.names=T, recursive=FALSE)
start_row<-1
lapply(files, function(x){
print(x)
xlFile<-read.xlsx2(x, sheetIndex = 1, startRow = 2, header =T) #Reads all columns as factors
#Write to Excel
write.xlsx(xlFile, file=outputFileName, sheetName = mnth, startRow = start_row)
start_row<- start_row + nrow(xlFile)
})
I am trying to read all the files with January (Ex: january2015, january 2016) and append the rows in the same sheet of a Consolidated xlsx file.
However I am getting the error:
Error in write.xlsx(xlFile, file = outputFileName, sheetName = mnth, :
unused argument (startRow = start_row)
The documentation clearly mentions that startRow is an optional parameter. Interestingly, sheetName is also an optional parameter but does not throw errors.
I have ran the code with startRow = start_row removed and it works as expected, i.e., the contents are repeatedly overwritten with only the contents of the last xls file prevailing.
UPDATE
I have changed the reading function from functions from XLConnect to avoid having the several functions with similar names, and I still get the same error:
Error in write.xlsx(xlFile, file = outputFileName, sheetName = placename, :
unused argument (startRow = start_row)
Here is the code with XLConnect:
lapply(files, function(x){
print(x)
xlFile<-readWorksheetFromFile(file = x, sheet=1, startRow=2)
str(xlFile)
l=list(dt,xlFile)
#Write to Excel
write.xlsx(xlFile, file=outputFileName, sheetName = mnth, startRow = start_row)
start_row<- start_row + nrow(xlFile)
})

Resources