So there is this example: https://developers.google.com/docs/api/how-tos/lists
How do I make nested list element? So how would look example adding Sub-Item One
?
As for version 1 of Google Docs API it's pretty complicated. Best way I found is to divide process of document creation in two phases:
Between first and second phase document is being refreshed on client side and named ranges got recalculated to positions. Thanks to this design I'm able to get it all done. Important trick is in phase 1 send all requests in reversed order as advised in tutorials.
Phase 1 requests would look more or less like this:
requests.add(
new Request()
.setCreateNamedRange(
new CreateNamedRangeRequest()
.setName(rangeName)
.setRange(
new Range()
.setStartIndex(1)
.setEndIndex(outputText.length() + 1))));
requests.add(
new Request()
.setInsertText(
new InsertTextRequest()
.setText(outputText)
.setLocation(new Location().setIndex(1))));
Notice that named range request is being create before inserting text. After preparation of all requests be the end of phase 1 and after they get reversed, named ranges requests are being correctly applied to just inserted piece of text.
Another important thing is rangeName
parameter. For single line types of text (title, headers, etc.) I don't care much and I name them html-ish (title, h1, h2, p). Fore multi line pieces (like bullet list from question) it's important to name each multi line section with unique name. So if I have 3 lists in my document each line in each of lists will be created with rangeName = "l" + x
so each line in list 1 would have named range named l1
, each line in list 2 would have named range named l2
and so on.
Then phase 2 comes. For single line ranges:
List<MyRange> myRanges = GoogleContentCreator.countSingleRanges(document, rangeName);
if (myRanges != null) {
List<Request> requests = new ArrayList<>();
for (MyRange myRange : myRanges) {
requests.add(new Request().setUpdateParagraphStyle(new UpdateParagraphStyleRequest()
.setRange(new Range()
.setStartIndex(myRange.getStart())
.setEndIndex(myRange.getEnd()))
.setParagraphStyle(new ParagraphStyle()
.setNamedStyleType(namedStyleType))
.setFields("namedStyleType")
));
}
return requests;
}
and for multi line ranges (here bullet list explicitly):
MyRange range = GoogleContentCreator.countListRange(document, rangeName);
if (range != null) {
List<Request> requests = new ArrayList<>();
requests.add(new Request().setCreateParagraphBullets(
new CreateParagraphBulletsRequest()
.setRange(new Range()
.setStartIndex(range.getStart())
.setEndIndex(range.getEnd()))
.setBulletPreset("BULLET_DISC_CIRCLE_SQUARE")));
return requests;
}
Crucial thing are countSingleRanges(...)
and countListRange(...)
methods. I'm not pasting implementation because it's quite messy but core concept is that countListRange(...)
returns one range which takes start of first occurrence of rangeName
tag and end of last occurrence of rangeName
tag. On the other hand countSingleRanges(...)
returns list of ranges exactly as they were placed in document.
After all this operations document gets correctly formatted and styled.
One thing I wasn't able to get to work in Google Docs API so far are tables but that was not scope of this question anyway.