setHeadingAttributes to redefine a heading style in Documents w/ GAS - google-apps-script

I am hoping to re-define the heading styles for a document. My understanding is that getHeadingAttributes and setHeadingAttributes would let me do this
https://developers.google.com/apps-script/reference/document/body#setheadingattributesparagraphheading-attributes
This is how I'm going about testing this --
function main() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
styledef=body.getHeadingAttributes(DocumentApp.ParagraphHeading.HEADING1);
Logger.log("Before: \n" + JSON.stringify(styledef) );
styledef[DocumentApp.Attribute.UNDERLINE] = true;
styledef[DocumentApp.Attribute.BACKGROUND_COLOR] = '#ffff00';
body.setHeadingAttributes(DocumentApp.ParagraphHeading.HEADING1, styledef);
styledef=body.getHeadingAttributes(DocumentApp.ParagraphHeading.HEADING1);
Logger.log("After: \n" + JSON.stringify(styledef));
}
This Body has its headings attributes modified, as revealed by the Logger output:
[17-10-04 09:20:53:379 MDT] Before:
{"FONT_SIZE":18,"ITALIC":false,"HORIZONTAL_ALIGNMENT":{},"INDENT_END":0,"INDENT_START":0,"LINE_SPACING":1,"UNDERLINE":false,"BACKGROUND_COLOR":null,"INDENT_FIRST_LINE":0,"SPACING_BEFORE":12,"SPACING_AFTER":0,"STRIKETHROUGH":false,"FOREGROUND_COLOR":"#000000","BOLD":true,"FONT_FAMILY":"Arial","VERTICAL_ALIGNMENT":{}}
[17-10-04 09:20:53:382 MDT] After:
{"FONT_SIZE":18,"ITALIC":false,"HORIZONTAL_ALIGNMENT":{},"INDENT_END":0,"INDENT_START":0,"LINE_SPACING":1,"UNDERLINE":true,"BACKGROUND_COLOR":"#ffff00","INDENT_FIRST_LINE":0,"SPACING_BEFORE":12,"SPACING_AFTER":0,"STRIKETHROUGH":false,"FOREGROUND_COLOR":"#000000","BOLD":true,"FONT_FAMILY":"Arial","VERTICAL_ALIGNMENT":{}}
UNDERLINE changed from false to true
BACKGROUND_COLOR changed from null to #ffff00
But in my document to which this script is bound, the styling of Heading 1 has not changed for existing paragraphs with that Heading. Nor are new paragraphs marked Heading 1 styled with the changes I've tried to make.
Incidentally, when I run that same function on NORMAL instead of HEADING1, the changes are instantly visible: Every Heading (Normal, Title, Subtitle, Heading 1, etc...) has the underline and background color applied.
I feel like I've fundamentally misunderstood the purpose of these methods (getHeadingAttributes, setHeadingAttributes). If not these methods, I'd like to find the correct way to re-define Heading stylings for a document. Can you point me in the right direction?
Many Thanks,

Haven't played around much of this yet, but check the Enum ParagraphHeading as it seems close to what you're getting at.
Use the ParagraphHeading enumeration to configure the heading style for ParagraphElement.
var body = DocumentApp.getActiveDocument().getBody();
// Append a paragraph, with heading 1.
var par1 = body.appendParagraph("Title");
par1.setHeading(DocumentApp.ParagraphHeading.HEADING1);
// Append a paragraph, with heading 2.
var par2 = body.appendParagraph("SubTitle");
par2.setHeading(DocumentApp.ParagraphHeading.HEADING2);
// Append a paragraph, with normal heading.
var par3 = body.appendParagraph("Text");
par3.setHeading(DocumentApp.ParagraphHeading.NORMAL);

Related

Centering in a gDoc after a replace

I am looking to replace a string within a Google Doc via an app script. The string will exist on a line, but after the replace, I want it to have a specific font, size and justification.
I've created a style to address all these attributes (I included both Horiz. and Vert. alignment) and most of it works fine. When the string is replaced, the replacement has the right font, size and bold attributes. For some reason, I cannot get the justification to get changed.
// Define the style for the replacement string.
var hdrStyle = {};
hdrStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] =
DocumentApp.HorizontalAlignment.CENTER;
hdrStyle[DocumentApp.Attribute.VERTICAL_ALIGNMENT] =
DocumentApp.VerticalAlignment.CENTER;
hdrStyle[DocumentApp.Attribute.FONT_FAMILY] = 'Calibri';
hdrStyle[DocumentApp.Attribute.FONT_SIZE] = 24;
hdrStyle[DocumentApp.Attribute.BOLD] = true;
{ then later }
documentBody = DocumentApp.openById(fileId).getBody();
hdrElem = documentBody.findText("old string").getElement();
hdrText = hdrElem.asText().setText("new string");
// Force our 'header style':
hdrElem.setAttributes(hdrStyle);
I've tried setting the style after the findText and (as here) after, but no change in centering.
I see there is a paragraph centering, but I am not clear how to 'get' the paragraph associated with the element that is returned on the find.
I'm hoping this is some simple set of calls - but have run out of ideas (and patience)..!
Any help would be appreciated!
You can use getParent() on hdrElem to get the parent paragraph to apply the styling to.
https://developers.google.com/apps-script/reference/document/text#getParent()
documentBody = DocumentApp.openById(fileId).getBody();
hdrElem = documentBody.findText("old string").getElement();
hdrText = hdrElem.asText().setText("new string");
var hdrParent = hdrElem.getParent()
// Force our 'header style':
hdrParent.setAttributes(hdrStyle);

How to set a certain number of spaces or indents before a Paragraph in Google Docs using Google Apps Script

I have a 20 line script, and I want to make sure that each paragraph is indented exactly once.
function myFunction() {
/*
This function turns the document's format into standard MLA.
*/
var body = DocumentApp.getActiveDocument().getBody();
body.setFontSize(12); // Set the font size of the contents of the documents to 9
body.setForegroundColor('#000000');
body.setFontFamily("Times New Roman");
// Loops through paragraphs in body and sets each to double spaced
var paragraphs = body.getParagraphs();
for (var i = 3; i < paragraphs.length; i++) { // Starts at 3 to exclude first 4 developer-made paragraphs
var paragraph = paragraphs[i];
paragraph.setLineSpacing(2);
// Left align the first cell.
paragraph.setAlignment(DocumentApp.HorizontalAlignment.LEFT);
// One indent
paragraph.editAsText().insertText(0, "\t"); // Adds one tab every time
}
var bodyText = body.editAsText();
bodyText.insertText(0, 'February 3, 1976\nMrs. Smith\nYour Name Here\nSocial Studies\n');
bodyText.setBold(false);
}
The code I have tried doesn't work. But my expected results are that for every paragraph in the for loop in myFunction(), there are exactly 4 spaces before the first word in each paragraph.
Here is a sample: https://docs.google.com/document/d/1sMztzhOehzheRdqumC6PLnvk4qJgUCSE0irjTZ0FjTQ/edit?usp=sharing
If the user uses Autoformat, but already has the paragraphs indented...
Update
I have investigated use of the Paragraph.setIndentFirstLine() method. When I set it to four, it sets it to 1 space. Now I realize this is because points and spaces are not the same thing. What number do I need to multiply by to get four spaces in points?
Let us consider a few basic identing operations: manual and by script.
The following image shows how to indent current paragraph (cursor stays inside this one).
Please note, the units are centimetres. Also note, that the paragraph does not include leading spaces or tabs, we have no need of them.
Suppose we would like to get the indent values in the script and apply them to the next paragraph. Look at the code below:
function myFunction() {
var ps = DocumentApp.getActiveDocument().getBody().getParagraphs();
// We work with the 5-th and 6-th paragraphs indeed
var iFirst = ps[5].getIndentFirstLine();
var iStart = ps[5].getIndentStart();
var iEnd = ps[5].getIndentEnd();
Logger.log([iFirst, iStart, iEnd]);
ps[6].setIndentFirstLine(iFirst);
ps[6].setIndentStart(iStart);
ps[6].setIndentEnd(iEnd);
}
If you run and look at the log, you will see something like this: [92.69291338582678, 64.34645669291339, 14.173228346456694]. No surprise, we have typographic points instead of centimetres. (1cm=28.3465pt) So we can measure and modify any paragraph indent values precisely.
Addition
For some reasons you might want to control spaces number at the beginning of the paragraph. It is also possible by scripting, but it has no effect on the paragraph's "left" or "right" indents.
Sample code below is for similar task: count leading spaces number of the 5-th paragraph and make the same number of spaces at the beginning of the next one.
function mySpaces() {
var ps = DocumentApp.getActiveDocument().getBody().getParagraphs();
// We work with the 5-th and 6-th paragraphs indeed
var spacesCount = getLeadingSpacesCount(ps[5]);
Logger.log(spacesCount);
var diff = getLeadingSpacesCount(ps[6]) - spacesCount;
if (diff > 0) {
ps[6].editAsText().deleteText(0, diff - 1);
} else if (diff < 0) {
var s = Array(1 - diff).join(' ');
ps[6].editAsText().insertText(0, s);
}
}
function getLeadingSpacesCount(p) {
var found = p.findText("^ +");
return found ? found.getEndOffsetInclusive() + 1 : 0;
}
We have used methods deleteText() and insertText() of the class Text for proper corrections and findText() to locate the spaces if any. Note, the last method argument is a string, representing a regular expression. It matches "all leading spaces", if they exist. See more details about regular expression syntax.

Add Text as Italics to Google Doc

I have an addon that I am working on for Google Docs, and I am trying to insert text as italics. I am trying to insert a Works Cited (MLA Formatting, as seen here1), and a title needs to be in italics, and the rest of the line needs to be in regular formatting. The methods I've tried either puts the whole document or the entire line in italics, which obviously doesn't work. Anyone have a solution?
The Text class has a setItalics() method that can be used to make text italicized. You will need to break up your larger body of text into smaller parts (one before the title, the title, and one after) to ensure that only the title is in italics.
Text Class setItalic
function myFunction() {
var body = DocumentApp.getActiveDocument().getBody();
var text = body.editAsText();
var textBeforeItalic = 'I wrote a book called ';
var title = 'Great Book';
var textAfterItalic = ', it is really good.';
text.insertText(0, textBeforeItalic+title+textAfterItalic);
text.setItalic(textBeforeItalic.length,textBeforeItalic.length+title.length,true);
}

How to split line of text (first half bold, second half not bold) when creating document using Google Script

Instead of:
doc.appendparagraph();
how do you add a line of text to your document without it returning to the next line?
I'm trying to break up a line of text and bold the first half the sentence with .setAttributes(bold);
bold which I've defined using....
var boldpl = {};
boldpl[DocumentApp.Attribute.BOLD] = true;.
Thank you.
I've figured out how to do this in a roundabout way using a merge feature, but how do you go about adding a new line instead of a new paragraph? There is no doc.appendText(); feature is there?
Also is there an easy way to make my document single spaced?
You've asked a lot of different questions there!
Given an existing paragraph, how can some portion of it be rendered in
bold while the rest remains normal?
A Document contains a Body, which can contain Paragraphs, each of which can contain other elements, including Text. You can get that Text either as a string - which you can't do much with - or as a Text Object. Here's an example of using the Text.setBold() method to change just some text in a paragraph to bold:
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var firstParagraph = body.getParagraphs()[0];
textElement = firstParagraph.editAsText();
textElement.setBold(0,6,true); // Set the 0th to 6th characters bold
Alternatively, you could use the Text.setAttributes() method with your custom attribute boldpl:
textElement.setAttributes(0,6, boldpl)
Starting with that building block, you could do things like:
Apply bold from the start of a paragraph until the first occurrence of a colon (:).
Apply bold to the first few words.
...or even apply bold to the first half!
textElement.setBold(0,
Math.floor((textElement.getText().length)/2),
true);
There is no doc.appendText(); feature is there?
No... but there is a Paragraph.appendText() method.
Also is there an easy way to make my document single spaced?
You can control the line spacing of text within paragraphs, by setting attributes on individual paragraphs. See Paragraph.setLineSpacing(). Here's a function that sets every paragraph in your document to single-spacing:
function singleSpace() {
var doc = DocumentApp.getActiveDocument();
var bodyElement = DocumentApp.getActiveDocument().getBody();
var paragraphs = bodyElement.getParagraphs();
// Set each paragraph to single-spaced
paragraphs.forEach( function( paragraph ) {
paragraph.setLineSpacing( 1.0 );
});
}

Proper way to use style attributes

I'm using DocumentApp.Attribute with mixed results. Here is an example:
var underline = {};
underline[DocumentApp.Attribute.UNDERLINE] = true;
underline[DocumentApp.Attribute.WIDTH] = 100;
underline[DocumentApp.Attribute.MARGIN_LEFT] = 10;
doc.appendParagraph("Paragraph text").setAttributes(underline);
The paragraph is created, and underlined, but the other two attributes don't get applied.
I think that you will find that a paragraph cannot have either Margin or width attributes ... they apply to the page or document as a whole. You might get the effect that you wish by using the Indent set of attributes.
This begs the next question "how do you set page attributes?"
MARGIN-LEFT appears as an attribute of the Body section so getActiveSection().setAttributes(style)
I am not sure what width refers to but you can do a getAttributes for each element type to track it down PAGE-WIDTH is an attribute of Body Section again. Play around with this code ...
function myFunction() {
var doc = DocumentApp.openById("1lqjkdfdsafgdsafsdaQI3kjtY");
var docele = doc.getActiveSection();
Logger.log(docele.getAttributes());
var para = doc.getParagraphs()[0];
var atts = para.getAttributes();
Logger.log(atts)
// Define a custom paragraph style.
var style = {};
style[DocumentApp.Attribute.WIDTH] = 100;
style[DocumentApp.Attribute.MARGIN_LEFT] = 200;
docele.setAttributes(style);
}
For me this gave body section attributes of {UNDERLINE=null, MARGIN_BOTTOM=72.0, PAGE_HEIGHT=792.0, BOLD=null, BACKGROUND_COLOR=null, FONT_SIZE=null, FONT_FAMILY=null, STRIKETHROUGH=null, MARGIN_LEFT=10.0, PAGE_WIDTH=612.0, LINK_URL=null, ITALIC=null, MARGIN_RIGHT=72.0, MARGIN_TOP=72.0, FOREGROUND_COLOR=null}
and paragraph attributes of {UNDERLINE=null, INDENT_END=8.25, LEFT_TO_RIGHT=true, BOLD=null, BACKGROUND_COLOR=null, FONT_SIZE=12, FONT_FAMILY=Comic Sans MS, SPACING_BEFORE=null, SPACING_AFTER=null, STRIKETHROUGH=null, INDENT_START=0.0, LINE_SPACING=null, LINK_URL=null, ITALIC=null, INDENT_FIRST_LINE=0.0, HORIZONTAL_ALIGNMENT=null, HEADING=null, FOREGROUND_COLOR=null}
This gives a clue to the alternative form for setting of attributes
docele.setAttributes({"FOREGROUND_COLOR":"#ff0000"})