I am trying to format certain columns using openxlsx to write an r data frame to an excel file.
Here is a snippet of the R data frame:
The square bracket part in the "seed" column is used to superscript the excel output.
Here is the code I used to write the file:
openxlsx::addWorksheet(wb, sheetName = 'data') # add sheet
openxlsx::writeData(wb, sheet ='data',
x=df, xy=c(1, 1),withFilter = T) # write data on workbook
# make quality codes superscript
for(i in grep("\\_\\[([A-z0-9\\s]*)\\]", wb$sharedStrings)){
# if empty string in superscript notation, then just remove the superscript notation
if(grepl("\\_\\[\\]", wb$sharedStrings[[i]])){
wb$sharedStrings[[i]] <- gsub("\\_\\[\\]", "", wb$sharedStrings[[i]])
next # skip to next iteration
}
# insert additional formatting in shared string
wb$sharedStrings[[i]] <- gsub("<si>", "<si><r>", gsub("</si>", "</r></si>", wb$sharedStrings[[i]]))
# find the "_[...]" pattern, remove brackets and udnerline and enclose the text with superscript format
wb$sharedStrings[[i]] <- gsub("\\_\\[([A-z0-9\\s]*)\\]",
"</t></r><r><rPr><vertAlign val=\"superscript\"/></rPr><t xml:space=\"preserve\">\\1</t></r><r><t xml:space=\"preserve\">",
wb$sharedStrings[[i]])
}
openxlsx::modifyBaseFont(wb, fontSize = 10, fontName = 'Arial')
# right-justify data
openxlsx::addStyle(wb, sheet = 'data',
style = openxlsx::createStyle(halign = "right"), rows = 1:nrow(df)+1, cols = 3:12, gridExpand = TRUE)
#apply to rows with "All" in column B
openxlsx::conditionalFormatting(wb,sheet = 'data',
cols = 1:ncol(df),
rows = 1:nrow(df)+1,
rule = 'LEFT($B2,3)="ALL"',
style = openxlsx::createStyle(textDecoration = 'bold', bgFill = '#dad9d9'))
# format numbers
openxlsx::addStyle(wb = wb, sheet = 'data',
style = openxlsx::createStyle(numFmt = "#,###.0"),
rows = 1:nrow(df)+1, cols = c(5:7,10:12),gridExpand = T)
# write excel file
openxlsx::saveWorkbook(wb, file="file.xlsx",
overwrite = TRUE)
The output looks like this:
I am trying to conditionally format the numbers in the seed/harv/yield/prod columns to be numbers, but the "F" values are creating a mixed-class vector at best. (I need these Fs!)
Any ideas?
Thanks!
Related
I am trying to format a mixed class vector in an xlsx output using openxlsx.
The code produces the excel file desired, but the numeric values are stored as test, how do I go about conditionally formatting the numbers?
wb <- openxlsx::createWorkbook() # create workbook
openxlsx::addWorksheet(wb, sheetName = 'data') # add sheet
openxlsx::writeData(wb, sheet ='data',
x=df, xy=c(1, 1),withFilter = T) # write data on workbook
# convert square brackets to superscript in xlsx output
for(i in grep("\\_\\[([A-z0-9\\s]*)\\]", wb$sharedStrings)){
# if empty string in superscript notation, then just remove the superscript notation
if(grepl("\\_\\[\\]", wb$sharedStrings[[i]])){
wb$sharedStrings[[i]] <- gsub("\\_\\[\\]", "", wb$sharedStrings[[i]])
next # skip to next iteration
}
# insert additioanl formatting in shared string
wb$sharedStrings[[i]] <- gsub("<si>", "<si><r>", gsub("</si>", "</r></si>", wb$sharedStrings[[i]]))
# find the "_[...]" pattern, remove brackets and udnerline and enclose the text with superscript format
wb$sharedStrings[[i]] <- gsub("\\_\\[([A-z0-9\\s]*)\\]",
"</t></r><r><rPr><vertAlign val=\"superscript\"/></rPr><t xml:space=\"preserve\">\\1</t></r><r><t xml:space=\"preserve\">",
wb$sharedStrings[[i]])
}
# write excel file
openxlsx::saveWorkbook(wb, file="test.xlsx",
overwrite = TRUE)
The output has the error triangles saying "Number stored as Text".
I tried adding, but no luck.
openxlsx::writeData(wb, sheet = 'data', names(df)[i], startCol = i, startRow = 1)
icol <- df[[i]]
for(j in seq_along(icol)){
x <- icol[[j]]
openxlsx::writeData(wb, sheet = 'data', x, startCol = i, startRow = j + 1)
}
}
I am trying to code a workbook script to match a format that auto changes any 0 value into a dash in much the same way clicking the "," in Excel would do. I tried to use numFmt = 'COMMA' however that was unable to produce the dashes. I tried a few custom formats however with no luck. Is there a code that can give me commas, no decimal places, and replace 0s with dashes? My current code is as follows.
addStyle(wb, sheet = "Sheet Name", style = createStyle(numFmt = "#,0"), rows = 4:15, cols = 2:17, gridExpand = T)
I guess this is more of an Excel question than R. In Excel custom type works like
positive number; negative number; zero
Hence if you want to convert zero to a dash then this has to be:
#,##0;-#,##0;-
So based on your code it will be:
addStyle(wb, sheet = "Sheet Name", style = createStyle(numFmt = "#,##0;-#,##0;-"), rows = 4:15, cols = 2:17, gridExpand = T)
I'm working with an Excel sheet in which some columns contain hyperlinks that are represented as text that is completely different from the actual address the hyperlinks point to. I want to use some R code to modify and subset the Excel sheet but keep the hyperlinks. I think I can do this by extracting those hyperlinks as an indexed character vector then re-introducing them into a new Excel document using the makeHyperlinkString() and writeFormula() functions. But I cannot figure out how to get a vector of the links themselves.
In case it matters, my intention is to do all the modifying and subsetting on a data.frame version of the Excel sheet rather than a workbook object.
Oh, now I think I got your problem. I thought there were only normal hyperlinks not Excel-Hyperlinks.
I think this may help you to get a vector of the hyperlinks, although its a bit messy.
library(openxlsx)
pathtofile = "path to .xlsx file"
df1 <- read.xlsx(xlsxFile = pathtofile,
sheet = 1, skipEmptyRows = FALSE,
colNames = F, rowNames = F,
startRow = 1)
## Sheet or Tabelle
Sheet = "Sheet" ## Or "Tabelle"
## Get Names of rows from Hyperlink column
rowIndex <- sub(x = df1[,1], pattern = paste0("(#'",Sheet,"\\d'!)"), replacement = "")
## Get the Sheet, where Hyperlinks are saved
SheetName <- regmatches(df1[,1], regexpr(text = df1[,1], pattern = paste0("(",Sheet,"\\d)")))
## Extract only the Sheet number
SheetIndex <- as.numeric(sub(x = SheetName, pattern = Sheet, replacement = ""))
## Get the row Indexes as numeric
RowIndexNum <- as.numeric(regmatches(rowIndex, regexpr(text = rowIndex, pattern = "\\d")))
## Get the column name as character
RowIndexName <- sub(x = rowIndex, pattern = "\\d", "")
## Create uppercase Letters
myLetters <- toupper(letters[1:26])
## Convert Row Name (character) to numeric (based on alphabetical order)
RowIndexNameNum <- match(RowIndexName, myLetters)
## If Hyperlinks only in 1 Sheet or several sheets
if (length(unique(SheetIndex)) == 1) {
dfLinks <- read.xlsx(xlsxFile = pathtofile,
sheet = unique(SheetIndex),
skipEmptyRows = FALSE,
colNames = F, rowNames = F,
rows = RowIndexNum[1]:tail(RowIndexNum,1),
cols = unique(RowIndexNameNum),
startRow = 1
);
} else {
dfLinks <- data.frame()
for (i in unique(SheetIndex)){
dfTmp <- read.xlsx(xlsxFile = pathtofile,
sheet = i,
skipEmptyRows = FALSE,
colNames = F, rowNames = F,
rows = RowIndexNum[1]:tail(RowIndexNum,1),
cols = unique(RowIndexNameNum),
startRow = 1)
dfLinks <- rbind(dfLinks, dfTmp)
}
}
dfLinks
This is how my Excel File looks like:
How can one create an excel file using openxlsx where the number formatting includes both comma thousand separators and 2 decimal places? I have tried the code below, but no luck on the formatting.
# Create Customer Dataset
cust <- data.table(Customer = c("Sue", "Ben", "Jason", "Cody"), Sales =
c(5654.3456, 29384.4, 729, .4093))
# Start Workbook
wb <- createWorkbook()
# Set Sheet Name
sheet = "Customers Report"
# Initiate worksheet within workbook
addWorksheet(wb = wb, sheet = sheet)
# Add Formatting to Spreadsheet
addStyle(wb = wb, sheet = sheet, style = createStyle(numFmt = "NUMBER"), rows = 2:6, cols = 2)
addStyle(wb = wb, sheet = sheet, style = createStyle(numFmt = "COMMA"), rows = 2:6, cols = 2, stack = TRUE)
# Write Customer Dataset to Spreadsheet
writeData(wb = wb, sheet = sheet, x = cust, headerStyle =
createStyle(textDecoration = "bold"))
# Write Workbook to File
saveWorkbook(wb = wb, file = "~/Desktop/Customer_Report.xlsx", overwrite = TRUE)
You can set the default formatting for the 2 decimal cases prior to adding the thousands format.
wb = createWorkbook()
options("openxlsx.numFmt" = "0.00") # 2 decimal cases formating
styleT <- createStyle(numFmt = "#,##0.00") # create thousands format
addStyle(wb, sheetName, styleT,
rows = 'yourrows',cols = 'yourcols',
gridExpand = T, stack = T) # add thousands format to designated cols and rows
This will ensure that the thousands formatting happens on a value that already has only 2 decimal cases.
I found the answer as I was writing the question, but I figured I would go ahead and post it in the event that someone else has the same question down the road. I found this answer via github openxlsx issue #75. Please see the below code block:
# Add Formatting to Spreadsheet
addStyle(wb = wb, sheet = sheet, style = createStyle(numFmt = "#,##0.00"), rows = 2:6, cols = 2)
I have found that you use "0" when you want there to be a digit there no matter if it is 0 and that you use "#" to represent a placeholder for a potential digit. For example, if the number is .4093 as shown above, then it would be formatted to 0.41 and if the number is 29384.4 as shown above, then it would be formatted to 29,384.40.
I am trying to format a data.frame I have created in R and can not seem to find a solution. By format I mean that I would like to bold/italicize the headers(i.e. names) of the data.frame and also color/highlight certain rows within the data.frame.
I tried researching on google/stackoverflow, but I could not find something applicable or directly useful. I also tried using CellStyle, but that would not allow me to bold/italicize the headers of the data.frame.
Any help is appreated!
You can go a long way with XLConnect package to format a data frame in Excel.
Here is code I have been using, which would be a good starting point for you learning it and exploring changes to suit you. Usage: save.xls(your data frame, the name you want to give the file with the .xlsx suffix, ....
save.xls <- function(df, filename, sheetname="Sheet", create=TRUE, rownames=NULL, startRow=1, zebra=F) {
require(XLConnect)
require(stringr)
if (is.matrix(df)) df <- as.data.frame(df)
if (!str_detect(filename, "\\.xlsx$")) filename <- str_c(filename, ".xlsx")
wb <- loadWorkbook(filename, create=create)
if (existsSheet(wb, sheetname))
warning(sprintf("Sheet %s already existed and was overwritten", sheetname))
createSheet(wb, name=sheetname)
if (!is.null(rownames)) df <- transform(df, rownames = row.names(df))
writeWorksheet(wb, df, startRow=startRow, sheet=sheetname, rownames=rownames)
if (zebra) {
color <- createCellStyle(wb)
setFillForegroundColor(color, color = XLC$"COLOR.LIGHT_CORNFLOWER_BLUE")
setFillPattern(color, fill = XLC$FILL.SOLID_FOREGROUND)
for (i in 1:ncol(df)) {
setCellStyle(wb, sheet = sheetname, row = seq(startRow+1, nrow(df)+2, 2), col = i,
cellstyle = color)
}
#prcntg <- createCellStyle(wb) see my script of XLConnect.R for how it worked
#dollar <- createCellStyle(wb)
#setDataFormat(prcntg, format = "0.0")
#setDataFormat(dollar, format = "$ 0.00")
border <- createCellStyle(wb)
setBorder(border, side = c("bottom","top"), type = XLC$"BORDER.THICK", color = XLC$"COLOR.RED")
setCellStyle(wb, sheet = "Sheet", row = startRow, col = 1:ncol(df), cellstyle = border)
setColumnWidth(wb, sheet = "Sheet", column = 1:ncol(df), width = -1) # this autosizes each column
}
saveWorkbook(wb)
}