Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] handling of threaded comments #674

Merged
merged 11 commits into from
Jul 16, 2023
Merged

[WIP] handling of threaded comments #674

merged 11 commits into from
Jul 16, 2023

Conversation

JanMarvin
Copy link
Owner

Currently there is no interface, but the following works. Therefore it should be straightforward to implement this. We could handle provider ids too.

Pinging: @JMPivette

library(openxlsx2)

## create a base file
wb <- wb_workbook() %>% wb_add_worksheet()

## prepare the file (this should happen in `wb_add_comment(as.comment = TRUE)`)
wb$Content_Types <- append(
  wb$Content_Types, 
  c(
    "<Default Extension=\"vml\" ContentType=\"application/vnd.openxmlformats-officedocument.vmlDrawing\"/>",
    "<Override PartName=\"/xl/threadedComments/threadedComment1.xml\" ContentType=\"application/vnd.ms-excel.threadedcomments+xml\"/>",
    "<Override PartName=\"/xl/persons/person.xml\" ContentType=\"application/vnd.ms-excel.person+xml\"/>"
  )
)

wb$worksheets_rels <- list(
  c(
    "<Relationship Id=\"rId3\" Type=\"http://schemas.microsoft.com/office/2017/10/relationships/threadedComment\" Target=\"../threadedComments/threadedComment1.xml\"/>", 
    "<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments\" Target=\"../comments1.xml\"/>", 
    "<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing\" Target=\"../drawings/vmlDrawing1.vml\"/>"
  )
)

wb$workbook.xml.rels <- append(
  wb$workbook.xml.rels,
  "<Relationship Id=\"rId5\" Type=\"http://schemas.microsoft.com/office/2017/10/relationships/person\" Target=\"persons/person.xml\"/>"
)


wb$worksheets[[1]]$legacyDrawing <- '<legacyDrawing r:id="rId1"/>'

wb$persons <- "<personList xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments\" xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"></personList>"

wb$threadComments <- "<ThreadedComments xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments\" xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"></ThreadedComments>"

wb$vml <- "<xml xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"><o:shapelayout v:ext=\"edit\"><o:idmap v:ext=\"edit\" data=\"1\"/></o:shapelayout><v:shapetype id=\"_x0000_t202\" coordsize=\"21600,21600\" o:spt=\"202\" path=\"m,l,21600r21600,l21600,xe\"><v:stroke joinstyle=\"miter\"/><v:path gradientshapeok=\"t\" o:connecttype=\"rect\"/></v:shapetype></xml>"

wb$comments[[1]] <- list()

wb$comments[[1]][[1]] <- list(
  ref = "",
  author = "",
  comment = character(),
  style = character()
)

## file is prepared
# wb$open()

st_userid <- function() {
  openxlsx2:::random_string(length = 16, pattern = "[a-z0-9]")
}

st_guid <- function() {
  paste0(
    openxlsx2:::random_string(length = 8, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 12, pattern = "[A-F0-9]")
  )
}

userid1 <- st_userid()
id1 <- st_guid()

userid2 <- st_userid()
id2 <- st_guid()

# add a few persons
wb$persons <- wb$persons %>% 
  xml_add_child(
    xml_child = c(
      sprintf("<person displayName=\"Jan Marvin Garbuszus\" id=\"{%s}\" userId=\"%s\" providerId=\"None\"/>", id2, userid2),
      sprintf("<person displayName=\"Jean-Marie Pivette\" id=\"{%s}\" userId=\"%s\" providerId=\"None\"/>", id1, userid1)
    )
  )

rnd <- st_guid()

# add a fictional comment and a reply
wb$threadComments[[1]] <- wb$threadComments[[1]] %>% 
  xml_add_child(
    xml_child = c(
      sprintf("<threadedComment ref=\"B1\" dT=\"2023-07-01T19:19:30.08\" personId=\"{%s}\" id=\"{%s}\"><text>Remember when I added threaded comments? Would be cool if we can have these in {openxlsx2}!</text></threadedComment>", id1, rnd),
      sprintf("<threadedComment ref=\"B1\" dT=\"2023-07-02T19:19:30.08\" personId=\"{%s}\" id=\"{%s}\" parentId=\"{%s}\"><text>Yes, I do remember! Let's check this out.</text></threadedComment>", id2, id2, rnd)
    )
  )

# add the vml
wb$vml[[1]] <- wb$vml[[1]] %>% 
  xml_add_child(xml_child = "<v:shape id=\"_x0000_s1027\" type=\"#_x0000_t202\" style=\"position:absolute;   margin-left:145pt;margin-top:2pt;width:104pt;height:69pt;z-index:2;   visibility:hidden\" fillcolor=\"#ffffe1 [80]\" strokecolor=\"none [81]\" o:insetmode=\"auto\"><v:fill color2=\"#ffffe1 [80]\"/><v:shadow color=\"none [81]\" obscured=\"t\"/><v:path o:connecttype=\"none\"/><v:textbox style=\"mso-direction-alt:auto\"><div style=\"text-align:left\"/></v:textbox><x:ClientData ObjectType=\"Note\"><x:MoveWithCells/><x:SizeWithCells/><x:Anchor>    2, 15, 0, 2, 3, 54, 4, 7</x:Anchor><x:AutoFill>False</x:AutoFill><x:Row>0</x:Row><x:Column>1</x:Column></x:ClientData></v:shape>")

# unfortunately we do not load the comment correctly
wb$comments[[1]][[1]] <- list(
  ref = "B1",
  author = sprintf("tc={%s}", rnd),
  comment = character(),
  style = character()
)

wb$add_data(dims = "B1", x = "no-comment")

if (interactive()) wb$open()
Screenshot 2023-07-04 at 00 04 15

@JanMarvin JanMarvin added the enhancement 😀 New feature or request label Jul 3, 2023
@JanMarvin
Copy link
Owner Author

library(openxlsx2)

st_guid <- function() {
  paste0(
    "{",
    openxlsx2:::random_string(length = 8, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 4, pattern = "[A-F0-9]"), "-",
    openxlsx2:::random_string(length = 12, pattern = "[A-F0-9]"),
    "}"
  )
}

st_userid <- function() {
  openxlsx2:::random_string(length = 16, pattern = "[a-z0-9]")
}

wb_add_persons <- function(wb, name) {
  
  xml_person <- xml_node_create(
    "person", 
    xml_attributes = c(
      displayName = name,
      id          = st_guid(),
      userId      = st_userid(),
      providerId  = "None"
    )
  )
  
  if (is.null(wb$persons)) {
    wb$persons <- xml_node_create(
      "personList",
      xml_attributes = c(
        `xmlns`   = "http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments",
        `xmlns:x` = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
      )
    )
  }
  
  wb$persons <- xml_add_child(wb$persons, xml_person)
  
  wb
}

wb_get_person <- function(name) {
  openxlsx2:::rbindlist(xml_attr(wb$persons, "personList", "person"))
}



## create a base file
wb <- wb_workbook() %>% wb_add_worksheet()

c1 <- create_comment(text = "this is a comment", author = "")

wb$add_comment(dims = "A1", comment = c1)
wb$add_comment(dims = "B1", comment = c1)

wb$Content_Types <- append(
  wb$Content_Types, 
  c(
    "<Default Extension=\"vml\" ContentType=\"application/vnd.openxmlformats-officedocument.vmlDrawing\"/>",
    "<Override PartName=\"/xl/threadedComments/threadedComment1.xml\" ContentType=\"application/vnd.ms-excel.threadedcomments+xml\"/>",
    "<Override PartName=\"/xl/persons/person.xml\" ContentType=\"application/vnd.ms-excel.person+xml\"/>"
  )
)

wb$worksheets_rels[[1]] <- append(
  wb$worksheets_rels[[1]],
  c(
    "<Relationship Id=\"rId3\" Type=\"http://schemas.microsoft.com/office/2017/10/relationships/threadedComment\" Target=\"../threadedComments/threadedComment1.xml\"/>"
  )
)

wb$workbook.xml.rels <- append(
  wb$workbook.xml.rels,
  "<Relationship Id=\"rId5\" Type=\"http://schemas.microsoft.com/office/2017/10/relationships/person\" Target=\"persons/person.xml\"/>"
)

wb <- wb %>% 
  wb_add_persons(name = "Jan Marvin") %>% 
  wb_add_persons(name = "John Doe")

wb_get_person()
#>   displayName                                     id providerId
#> 1  Jan Marvin {9F46CFFC-F611-73CA-3033-846B134496A9}       None
#> 2    John Doe {8220D9CF-459E-2B92-2C65-9044D4BEF1C4}       None
#>             userId
#> 1 90i02y3av46fwuqk
#> 2 7oxa3pjty39hbk97

wb$threadComments <- "<ThreadedComments xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2018/threadedcomments\" xmlns:x=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"></ThreadedComments>"

c1_id <- st_guid()
c2_id <- st_guid()
c3_id <- st_guid()

# add a fictional comment and a reply
wb$threadComments[[1]] <- wb$threadComments[[1]] %>% 
  xml_add_child(
    xml_child = c(
      sprintf("<threadedComment ref=\"A1\" dT=\"2023-07-01T19:19:30.08\" personId=\"%s\" id=\"%s\"><text>Remember when I added threaded comments? Would be cool if we can have these in {openxlsx2}!</text></threadedComment>", wb_get_person()$id[2], c1_id),
      sprintf("<threadedComment ref=\"A1\" dT=\"2023-07-02T19:19:30.08\" personId=\"%s\" id=\"%s\" parentId=\"%s\"><text>Yes, I do remember! Let's check this out.</text></threadedComment>", wb_get_person()$id[1], c2_id, c1_id),
      sprintf("<threadedComment ref=\"A1\" dT=\"2023-07-02T19:19:30.08\" personId=\"%s\" id=\"%s\" parentId=\"%s\"><text>Yes, I do remember! Let's check this out.</text></threadedComment>", wb_get_person()$id[1], st_guid(), c1_id)
    )
  ) %>% 
  xml_add_child(
    xml_child = c(
      sprintf("<threadedComment ref=\"B1\" dT=\"2023-07-01T19:19:30.08\" personId=\"%s\" id=\"%s\" done=\"1\"><text>Remember when I added threaded comments? Would be cool if we can have these in {openxlsx2}!</text></threadedComment>", wb_get_person()$id[2], c3_id)
    )
  )

# unfortunately we do not load the comment correctly
wb$comments[[1]][[1]] <- list(
  ref = "A1",
  author = sprintf("tc=%s", c1_id),
  comment = "<t>open</t>",
  style = FALSE
)
wb$comments[[1]][[2]] <- list(
  ref = "B1",
  author = sprintf("tc=%s", c3_id),
  comment = "<t>done</t>",
  style = FALSE
)

wb$add_data(dims = "A1", x = "open")
wb$add_data(dims = "B1", x = "done")

# wb$save("/tmp/test.xlsx")
# unlink("/tmp/test", recursive = TRUE)
# unzip("/tmp/test.xlsx", exdir = "/tmp/test")

if (interactive()) wb$open()

@JanMarvin JanMarvin merged commit caaf15e into main Jul 16, 2023
@JanMarvin JanMarvin deleted the threadedComments branch July 16, 2023 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 😀 New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant