Open Fergus-Boyd opened 6 years ago
I've writen this small snippet to replace certain substrings with substrings in superscript (for example "1)"). We use this to create footnotes in our excel-sheets. The snippet replaces "1)" to "9)" with "1)" to "9)" in superscript.
`for (i in grep("\*(\d)", wb$sharedStrings)) {
wb$sharedStrings[i]=gsub("
wb$sharedStrings[i]=gsub("\*(\d))", "
Could be easily adappted to do subscript or reformat any other substring. Be aware that this migth destroy any other cell-specific text formating. I have not tested that.
I modified your function to make it more general, you only need one input:
text: "normal text [superscript] ~ subscript ~" (avoid spaces between ~)
addSuperSubScriptToCell_general <- function(wb,
sheet,
row,
col,
texto,
size = '10',
colour = '000000',
font = 'Arial',
family = '2',
bold = FALSE,
italic = FALSE,
underlined = FALSE) {
placeholderText <- 'This is placeholder text that should not appear anywhere in your document.'
openxlsx::writeData(wb = wb,
sheet = sheet,
x = placeholderText,
startRow = row,
startCol = col)
#finds the string that you want to update
stringToUpdate <- which(sapply(wb$sharedStrings,
function(x){
grep(pattern = placeholderText,
x)
}
)
== 1)
#splits the text into normal text, superscript and subcript
normal_text <- str_split(texto, "\\[.*\\]|~.*~") %>% pluck(1) %>% purrr::discard(~ . == "")
sub_sup_text <- str_extract_all(texto, "\\[.*\\]|~.*~") %>% pluck(1)
if (length(normal_text) > length(sub_sup_text)) {
sub_sup_text <- c(sub_sup_text, "")
} else if (length(sub_sup_text) > length(normal_text)) {
normal_text <- c(normal_text, "")
}
# this is the separated text which will be used next
texto_separado <- map2(normal_text, sub_sup_text, ~ c(.x, .y)) %>%
reduce(c) %>%
purrr::discard(~ . == "")
#formatting instructions
sz <- paste('<sz val =\"',size,'\"/>',
sep = '')
col <- paste('<color rgb =\"',colour,'\"/>',
sep = '')
rFont <- paste('<rFont val =\"',font,'\"/>',
sep = '')
fam <- paste('<family val =\"',family,'\"/>',
sep = '')
#if its sub or sup adds the corresponding xml code
sub_sup_no <- function(texto) {
if(str_detect(texto, "\\[.*\\]")){
return('<vertAlign val=\"superscript\"/>')
} else if (str_detect(texto, "~.*~")) {
return('<vertAlign val=\"subscript\"/>')
} else {
return('')
}
}
#get text from normal text, sub and sup
get_text_sub_sup <- function(texto) {
str_remove_all(texto, "\\[|\\]|~")
}
#formating
if(bold){
bld <- '<b/>'
} else{bld <- ''}
if(italic){
itl <- '<i/>'
} else{itl <- ''}
if(underlined){
uld <- '<u/>'
} else{uld <- ''}
#get all properties from one element of texto_separado
get_all_properties <- function(texto) {
paste0('<r><rPr>',
sub_sup_no(texto),
sz,
col,
rFont,
fam,
bld,
itl,
uld,
'</rPr><t xml:space="preserve">',
get_text_sub_sup(texto),
'</t></r>')
}
# use above function in texto_separado
newString <- map(texto_separado, ~ get_all_properties(.)) %>%
reduce(paste, sep = "") %>%
{c("<si>", ., "</si>")} %>%
reduce(paste, sep = "")
# replace initial text
wb$sharedStrings[stringToUpdate] <- newString
}
I've written the following function to enable me to do this write XML directly to the 'shared strings' list. Is there a more straightforward way this could be achieved?: