【发布时间】:2020-07-08 14:30:36
【问题描述】:
将 Google Docs/Drive API 与 Node 一起使用,我成功地制作了一项服务,该服务可生成“模板”样式的文档,该文档具有命名范围供其他用户写入。我想使用 Google Docs API 来阅读在这些范围内输入的文本,但看不到这样做的干净方式。鉴于我有每个范围的开始和结束索引,我认为这将非常简单!不幸的是,我看不到任何内置的方法?
目前看来我将不得不请求整个谷歌文档,并且对于我正在观看的每个范围,比较每个节点的开始/结束索引并递归遍历树直到它们匹配。没有更好的方法吗?
干杯
编辑:
以下 Tanaike 的解决方案更简洁,但我已经有了一个适用于我的 Firebase 功能的版本,所以我想我不妨分享一下。此代码检索具有给定 ID 的 Google Doc,并将 namedRanges 的内容作为字符串存储在 Firebase 实时数据库中,通过“BBCode”样式标签保持图像和表格的完整性。下面的相关代码(请注意,我知道每个 namedRange 都在一个表格单元格内,这样更容易找到它们):
async function StoreResponses(oauth2Client, numSections, documentId, meetingId, revisionId, roomId)
{
var gdocsApi = google.docs({version: 'v1', auth: oauth2Client});
return gdocsApi.documents.get({ "documentId": documentId })
.then((document) => {
var ranges = document.data.namedRanges;
var docContent = document.data.body.content;
var toStore = [];
for(var i = 0; i < numSections; i++)
{
var range = ranges[`zoomsense_section_${i}`].namedRanges[0].ranges[0]
// loop through document contents until we hit the right index
for(var j = 0; j < docContent.length; j++)
{
if(docContent[j].startIndex <= range.startIndex && docContent[j].endIndex >= range.endIndex)
{
// we know that the ranges are inside single table cells
var sectionContents = docContent[j].table.tableRows[0].tableCells[0].content;
toStore.push(readStructuralElementsRecursively(document, sectionContents));
}
}
}
return db.ref(`/data/gdocs/${meetingId}/${roomId}/${documentId}/revisions/${revisionId}/responses`).set(toStore);
})
.catch((exception) => {
console.error(exception)
res.status(500).send(exception);
})
}
// uses https://developers.google.com/docs/api/samples/extract-text
function readStructuralElementsRecursively(document, elements)
{
var text = "";
elements.forEach(element => {
if(element.paragraph)
{
element.paragraph.elements.forEach(elem => {
text += readParagraphElement(document, elem);
});
}
else if(element.table)
{
// The text in table cells are in nested Structural Elements, so this is recursive
text += "[table]"
element.table.tableRows.forEach(row => {
text += "[row]"
row.tableCells.forEach(cell => {
text += `[cell]${readStructuralElementsRecursively(document, cell.content)}[/cell]`;
})
text += "[/row]"
})
text+= "[/table]"
}
});
return text;
}
// handle text and inline content
function readParagraphElement(document, element)
{
if(element.textRun)
{
// standard text
return element.textRun.content;
}
if(element.inlineObjectElement)
{
var objId = element.inlineObjectElement.inlineObjectId;
var imgTag = "\n[img]404[/img]"
try
{
var embeddedObj = document.data.inlineObjects[objId].inlineObjectProperties.embeddedObject;
if(embeddedObj.imageProperties)
{
// this is an image
imgTag = `[img]${embeddedObj.imageProperties.contentUri}[/img]`
}
else if(embeddedObj.embeddedDrawingProperties)
{
// this is a shape/drawing
// can't find any way to meaningfully reference them externally,
// so storing the ID in case we can do it later
imgTag = `[drawing]${objId}[/drawing]`
}
}
catch(exception)
{
console.log(exception)
}
return imgTag;
}
}
【问题讨论】:
-
我提出了一种解决方法来实现您的目标作为答案。你能确认一下吗?如果这不是您期望的方向,我深表歉意。
标签: node.js google-apps-script google-docs-api named-ranges