我想知道是否可以使用 Google Apps 脚本在 Google 文档中执行以下任一操作:
Google Apps 脚本为
Paragraph
类的方向性提供了一个接口:它具有 setLeftToRight()
方法以及 LEFT_TO_RIGHT
属性。但是,没有与 TableCell
、TableRow
或 Table
等同的符号。此外,尝试在从右到左定向的段落之后添加表格会生成从左到右定向的表格。
相比之下,使用 Google 文档的图形界面,当光标位于从右到左的表格内时创建表格时,会生成从右到左的表格。此外,在任何单元格内设置方向都会更改该单元格和整个表格的方向(尽管其他单元格保持其原始方向性)。
我没有找到解决此问题的方法,并且希望得到一些想法。同时,我已向 Google 产品团队提交了问题。以下示例代码也是已提交问题的一部分,但在此处给出,以便无需 Google 帐户即可访问:
// run the following function on a document.
// it will append several paragraphs to the document, demonstrating the issue.
function tableDirectionIssueExample() {
var rtlAttrs = {};
rtlAttrs[DocumentApp.Attribute.LEFT_TO_RIGHT] = false;
var ltrAttrs = {};
ltrAttrs[DocumentApp.Attribute.LEFT_TO_RIGHT] = true;
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var par;
par = body.appendParagraph("The next table is in a left-to-right direction:");
par.setAttributes(ltrAttrs);
var tableLtr = body.appendTable([["a","b"],["c","d"]]);
par = body.appendParagraph("The next table should be in a right-to-left direction, as that is what the graphical interface does, but it isn't:");
par.setAttributes(rtlAttrs);
var tableRtl = body.appendTable([["a","b"],["c","d"]]);
body.appendParagraph("Getting the left-to-right attribute of a table results in the value: " + tableLtr.getAttributes()[DocumentApp.Attribute.LEFT_TO_RIGHT]);
body.appendParagraph("The following table will be created with a default direction, and then we'll attempt setting the left-to-right property to false, but to no avail...");
var tableExplicitRtl = body.appendTable([["a","b"],["c","d"]]);
tableExplicitRtl.setAttributes(rtlAttrs);
tableExplicitRtl.getRow(0).setAttributes(rtlAttrs);
tableExplicitRtl.getRow(0).getCell(0).setAttributes(rtlAttrs);
tableExplicitRtl.getRow(0).getCell(0).getChild(0).setAttributes(rtlAttrs);
body.appendParagraph("You'll notice the only thing that was succesful is setting the paragraph of the first cell as right-to-left, but that didn't affect the rest of the table. That is again unlike the graphical interface, where hitting a direction button on any cell changes the directionality of the entire table.");
}
不是100%,但至少看起来不错。
var collectedText = {
questionSection: {
heading: "סעיף 13 - מקום ותפקידו",
question: "שאלה מס' 1",
description: "ספרייה : ספרים",
options: [
"א) חווה : חיות",
"ב) שוק : ירקות",
"ג) מוזיאון : אומנות",
"ד) מטבח : סירים"
]
},
originalRelationshipSection: {
heading: "הקשר המקורי:",
rowsCells:{
row1:{
cell1:"הסבר הקשר",
cell2:"מושג 2 (שמאל)",
cell3:"מושג 1 (ימין)"
},
row2:{
cell1:"ספרייה היא מקום שתפקידה העיקרי הוא לאחסן ספרים",
cell2:"ספרים",
cell3:"ספרייה"
}
},
isolationHeading: "בידוד הקשר המקורי:",
isolationText: "מושג א הוא מקום שתפקדו המרכזי קשור למושג ב.",
tipHeading: "טיפ:",
tipText: "יש לבחור מקום שבו התפקיד המרכזי ברור וממוקד, כמו חווה וחיות או ספרייה וספרים. מקומות רב-תכליתיים, כמו שוק או מטבח, פחות מתאימים לקשר זה."
},
answerSection: {
heading: "מעבר על התשובות:",
rowsCells:{
row1: {
cell1: "האם התשובה נכונה?",
cell2: "הסבר הקשר",
cell3: "מושג 2 (שמאל)",
cell4: "מושג 1 (ימין)",
cell5: "מס'",
},
row2: {
cell1: "❌ מושג א (שדה תעופה) הוא מקום שתפקידו המרכזי קשור למושג ב (מטוסים)",
cell2: "שדה תעופה הוא מקום שמשרת מטוסים, אך תפקידו כולל מגוון פעילויות נוספות ולכן פחות ממוקד",
cell3: "מטוסים",
cell4: "שדה תעופה",
cell5: "א",
},
row3: {
cell1: "❌ מושג א (תחנת דלק) הוא מקום שתפקידו המרכזי קשור למושג ב (מכוניות)",
cell2: "תחנת דלק מספקת דלק למכוניות, אך מכוניות הן עצמים דוממים",
cell3: "מכוניות",
cell4: "תחנת דלק",
cell5: "ב",
},
row4: {
cell1: "❌ מושג א (אסם) הוא מקום שתפקידו המרכזי קשור למושג ב (תרנגולות)",
cell2: "אסם עם קשר חקלאי, ללא ספציפיות לתרנגולות",
cell3: "תרנגולות",
cell4: "אסם",
cell5: "ג",
},
row5: {
cell1: "✅ מושג א (בית ספר) הוא מקום שתפקידו המרכזי קשור למושג ב (תלמידים)",
cell2: "בית ספר הוא מקום שתפקדו המרכזי הוא ללמד תלמידים ולכן מקיים את הקשר",
cell3: "תלמידים",
cell4: "בית ספר",
cell5: "ד",
}
}
}
};
function createCompleteSectionOnSeparatePages() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
function getParagraphIndexAndDeletePlaceholderText (){
const functionName = 'getParagraphIndexAndDeletePlaceholderText';
try{
var searchResult = body.findText("rat2");
if (!searchResult) {
throw new Error('The text "rat2" was not found in the document.');
}
var element = searchResult.getElement();
var paragraphIndex = body.getChildIndex(element.getParent());
// Clear the existing placeholder text
element.asText().deleteText(0, "rat2".length - 1);
return paragraphIndex;
} catch (err) {
console.log({functionName, success:false, err})
}
}
function createTable(rowsCells) {
const table = [];
for (const [_, rowData] of Object.entries(rowsCells)) {
const row = Object.values(rowData);
table.push(row);
}
return table;
}
function insertLineBreak(currentIndex){
body.insertParagraph(currentIndex++, '').setFontSize(12).setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
return currentIndex;
}
function addTextRightToLeft(currentIndex,{text, fontSize = 12, isBold = false, isNewLine = true, isHeading2 = false, isHeading3 = false}){
if(isHeading2) {
body.insertParagraph(currentIndex++, text).setLeftToRight(false).setHeading(DocumentApp.ParagraphHeading.HEADING2)
return currentIndex;
}
if(isHeading3) {
body.insertParagraph(currentIndex++, text).setLeftToRight(false).setHeading(DocumentApp.ParagraphHeading.HEADING3)
return currentIndex;
}
const newLine = isNewLine ? '\n':'';
let asText = body.insertParagraph(currentIndex++, '').setLeftToRight(false).appendText(newLine+text).editAsText();
if(isBold) asText=asText.setBold(isBold);
if(fontSize) asText=asText.setFontSize(fontSize);
// body.insertParagraph(currentIndex++, '').setLeftToRight(false).appendText(newLine+text).editAsText().setFontSize(fontSize).setBold(isBold);
return currentIndex;
}
function styleTableRow(currentRow,{isBold = false, isCenter = false}){
const horizontalAlignment = isCenter ? DocumentApp.HorizontalAlignment.CENTER : DocumentApp.HorizontalAlignment.LEFT;
for (var i = 0; i < currentRow.getNumCells(); i++) {
var cell = currentRow.getCell(i);
cell.getChild(0).asParagraph().setLeftToRight(false).setBold(isBold).setAlignment(horizontalAlignment);
}
}
function styleTableColumns(table,{columnWidths}){
if(!columnWidths) return;
for (const [index,columnWidth] in columnWidths.entries()){
table.setColumnWidth(index+1,columnWidth);
}
}
// Function to insert the question section
function insertQuestionSection(currentIndex) {
var section = collectedText.questionSection;
// Add heading 2
currentIndex = addTextRightToLeft(currentIndex,{text:section.heading, isHeading2:true});
// Add question and description
currentIndex = addTextRightToLeft(currentIndex,{text:section.question, isHeading3:true});
// insert line break
currentIndex = insertLineBreak(currentIndex);
// insert question original couple
currentIndex = addTextRightToLeft(currentIndex,{text:section.description, isNewLine:false});
// insert line break
currentIndex = insertLineBreak(currentIndex);
// Add options
section.options.forEach(function (option) {
currentIndex = addTextRightToLeft(currentIndex,{text:option, isNewLine:false});
});
body.insertPageBreak(currentIndex++); // Add page break
return currentIndex;
}
// Function to insert the original relationship section
function insertOriginalRelationshipSection(currentIndex) {
var section = collectedText.originalRelationshipSection;
// Add heading
currentIndex = addTextRightToLeft(currentIndex,{text:section.heading,isBold:true, isNewLine:false});
// Add table
const tableContent = createTable(section.rowsCells)
var table = body.insertTable(currentIndex++, tableContent);
// style table
let tableRows = []
for (var i = 0; i < table.getNumRows(); i++) {
tableRows.push(table.getRow(i))
}
for (const [index, value] of tableRows.entries()){
// header line in bold
styleTableRow(value,{isBold:index === 0, isCenter:true})
}
// Add isolation heading and text RTL
currentIndex = addTextRightToLeft(currentIndex,{text:section.isolationHeading,isBold:true});
currentIndex = addTextRightToLeft(currentIndex,{text:section.isolationText,isNewLine:false});
currentIndex = addTextRightToLeft(currentIndex,{text:section.tipHeading, isBold:true});
currentIndex = addTextRightToLeft(currentIndex,{text:section.tipText,isNewLine:false});
body.insertPageBreak(currentIndex++); // Add page break
return currentIndex;
}
// Function to insert the answer section
function insertAnswerSection(currentIndex) {
var section = collectedText.answerSection;
// Add heading
currentIndex = addTextRightToLeft(currentIndex,{text:section.heading, isBold:true});
// add table
const tableContent = createTable(section.rowsCells)
var table = body.insertTable(currentIndex++, tableContent);
// style table
let tableRows = []
for (var i = 0; i < table.getNumRows(); i++) {
tableRows.push(table.getRow(i))
}
for (const [index, value] of tableRows.entries()){
// header line in bold
styleTableRow(value,{isBold:index === 0, isCenter:index === 0})
}
// styleTableColumns(table,{columnWidths:[5,5,5,10,10]})
body.insertPageBreak(currentIndex++); // Add page break
return currentIndex;
}
// Insert sections
const paragraphIndex = getParagraphIndexAndDeletePlaceholderText()
var currentIndex = paragraphIndex;
currentIndex = insertQuestionSection(currentIndex);
currentIndex = insertOriginalRelationshipSection(currentIndex);
insertAnswerSection(currentIndex);
Logger.log("Content inserted on separate pages, starting after the placeholder.");
}