How to programmatically control the guides (rules of third)?

Viewed 133

Is there any way to control guides (rules of third) in a Google Slides presentation. As far as I have read the Google Apps Script documentation, there is no method to control the guides.

I already tried lines that would behave like guides (rules of third), but these are not "real" guides. The user can delete these lines, and these lines are limited to the slide page area.

See the picture to get the difference between lines and guides (rules of third):

lines and guides difference

To enable the guides (rules of third) go here:

guides

2 Answers

A feature request to allow guides to be controlled via SlidesApp or Slides API is submitted to the issue tracker. Please star it if you find that the feature would be useful.

Short answer

As already mentioned, unfortunately, this is not currently possible either via the SlidesApp service or the Slides API.

Workaround

It is actually possible to make lines stretch outside of the slide bounds by passing a negative integer as an argument of insertLine. As for being able to delete the lines, guides can also be "deleted" by user if they drag the guide out of the slide boundaries.

The only property of the guides that I could not emulate is hiding them when presenting (as real guides are hidden).

Below is a workaround similar to your approach (creating a grid of Lines):

Guides

/**
 * @summary emulates adding guides to the Slide
 * 
 * @param {{
 *  rows : (number|1),
 *  deleteOld : (boolean|true),
 *  cols : (number|1),
 *  color : string
 * }} 
 */
const showGuides = ({ deleteOld = true, rows = 1, cols = 1, color = "#d3d3d3" } = {}) => {

    const presentation = SlidesApp.getActivePresentation();
    const currPage = presentation.getSelection().getCurrentPage();

    const prop = "guides";

    const store = PropertiesService.getUserProperties();

    /** @type {string[]} */
    let guideRefs = JSON.parse(store.getProperty(prop) || "[]");

    const lines = currPage.getLines();

    const oldLines = lines.filter((line) => guideRefs.includes(line.getObjectId()));

    if (deleteOld) {
        oldLines.forEach(line => line.remove());

        guideRefs = removeElements(guideRefs, oldLines.map(l => l.getObjectId()));
    }

    const currWidth = presentation.getPageWidth();
    const currHeight = presentation.getPageHeight();

    const xStep = Math.floor(currWidth / cols);
    const yStep = Math.floor(currHeight / rows);

    const newGuides = [];

    const maxScreen = 4096;

    for (let x = 0; x <= cols; x++) {
        const line = currPage.insertLine(
            SlidesApp.LineCategory.STRAIGHT,
            xStep * x, -maxScreen, xStep * x, currHeight + maxScreen
        );

        const fill = line.getLineFill();
        fill.setSolidFill(color);

        const oid = line.getObjectId();
        guideRefs.push(oid);
        newGuides.push(line);
    }

    for (let y = 0; y <= rows; y++) {
        const line = currPage.insertLine(
            SlidesApp.LineCategory.STRAIGHT,
            -maxScreen, yStep * y, currWidth + maxScreen, yStep * y
        );

        const fill = line.getLineFill();
        fill.setSolidFill(color);

        const oid = line.getObjectId();
        guideRefs.push(oid);
        newGuides.push(line);
    }

    store.setProperty(prop, JSON.stringify(guideRefs));
};

Utilities

/**
 * @summary removes elements from an array
 * @param {any[]} arr 
 * @param {...any} elems
 * @returns {any[]}
 */
const removeElements = (arr, ...elems) => arr.filter((elem) => !elems.includes(elem));

Demo

workaround test

Slides guides cannot currently be managed programmatically.

Guides are a fairly recent addition to Slides (since April '18), and they haven't been implemented on Slides API yet, let alone on Apps Script. The only way to manage them for now is manually, through the Slides editor.

File a Feature Request:

I'd suggest you to file a Feature Request on this Issue Tracker component regarding the implementation of this functionality on Slides API. I did some research on that component and it seems like no one has requested this yet.

Once that's done, you could manage this from Apps Script via Advanced Slides Service, at least until Apps Script built-in classes and methods were implemented.

Related