要怎麽快速搜集在 Slides 中出现的特定文字,并在 Sheet 上标示其出现的页码?今天的结果预计是这样——
今天的主题情在在於,现代沟通很常会用 PPT。很多时候会需要来回传 PPT,而为了传达说「这一页我想改什麽」,我们会使用「注解」如下图(以 D21 生成的文为例,在拿给主管後收到了回馈),大大的被写上了「距离太远」。
传达上的另一种方式,是「另外开一个新的文字方块」来沟通,容易看到被大大的贴上了「主标换行」。
那当我们在「检查简报时」会有个重复的行为,就是每次要改简报,我们就要从头到尾的简报都看过是不是还有「待办事项」,有时还是难免漏掉一些小部分。有没有什麽方式,可以帮助我们自动地搜集所有的 Comment 或标示上「TO-DO」的文字方块,并整理成 Google Sheet 呢?而对应的关键问题是——
好,那就让我们开始吧!
TO-DO
预计会变成这样——
今天我们用 Google Sheet 作为连结 GAS 的管道,让我们借用 D14 的影片。
一样第一次按下 GAS 中的「执行」会有「存取验证」需要大家按一下。这边仍是借用一下 D2 的影片。
接着,我们抓出要核对的 Presentation ID,这边我们用 D21 的「自动化爲铁人赛的每一篇贴文生封面图」 的结果 Slides 为例。抓出 ID 的示范如下——
并将这 ID 到我们的 GAS 当中设定为一个参数。
var target_slide_ID = "your_pres_ID_here"
有夥伴反应这边不确定怎麽做,就一起准备了影片——
接着,就是读取简报了,直接作为 Step 2
这边我们就用 SlidesApp.openById()
搭配 getSlides()
来取得所有的投影片。接着再用一个 for 回圈 Print 出所有档案们。
function listAllTodos(){
// READ SLIDES
let pres = SlidesApp.openById(target_slide_ID);
let slides = pres.getSlides();
Logger.log("The number of slides are "+ slides.length)
for(let i = 0; i<slides.length; i++){
Logger.log("Read Slides No."+ i)
}
}
跑起来长这样——
这次我们要读的特定文字是「To-Do
」,逻辑是,搜寻每一张投影片的元素(Page Elements)确认,如果是属於含有文字方块的(Shape),那就确认他呈现的文字中,前五个是不是 "TO-DO"
,是的话就抓出来并写上页数。程序码结合前面步骤就会变成——
function listAllTodos(){
// READ SLIDES
let pres = SlidesApp.openById(target_slide_ID);
let slides = pres.getSlides();
// LIST TARGET TEXT and page
for(let i = 0; i<slides.length; i++){
let slide = slides[i]
let page_elements = slide.getPageElements();
for(page_element of page_elements){
if(page_element.getPageElementType() == SlidesApp.PageElementType.SHAPE){
let text = page_element.asShape().getText().asRenderedString();
if (text.slice(0,5)=="TO-DO"){
Logger.log("Slide No."+i+ " has a to-do:"+ text)
}
}
}
}
}
让我们来看看会跑怎麽样——
OK,那却时有读到我们在 Slide 第 12 与 13 页中的 TO-DO
以及其文字。接着就要写入 Google Sheet 中了。
出现我们的老朋友 writeData()
拉!程序码让大家复习——
function writeData(data){
let sheet = SpreadsheetApp.getActiveSheet();
let starting_row = 2;
let starting_col = 1;
let num_row = data.length;
let num_col = data[0].length;
let range = sheet.getRange(starting_row, starting_col, num_row, num_col);
range.setValues(data);
}
再结合并改写我们的前面的部分
function listAndRecordAllTodos(){
// READ SLIDES
let pres = SlidesApp.openById(target_slide_ID);
let slides = pres.getSlides();
let result=[];
let update_time = new Date().toLocaleDateString();
// LIST TARGET TEXT and page
for(let i = 0; i<slides.length; i++){
let slide = slides[i]
let page_elements = slide.getPageElements();
for(page_element of page_elements){
if(page_element.getPageElementType() == SlidesApp.PageElementType.SHAPE){
let text = page_element.asShape().getText().asRenderedString();
let starting_text = text.slice(0,5)
if (starting_text=="TO-DO"){
Logger.log("Slide No."+(i+1)+ " has a to-do:"+ text);
result.push([update_time, i+1, text]);
}
}
}
}
writeData(result)
}
让我们来看看会跑怎麽样——
好,那看起来有写入成功!但其实我们还有件事没做,就是「读取备注」(Read Comment)
会把「读取备注」分开写,是因为它相对比较复杂。目前查到能「读备注」的 Google 功能并不是现有的,而是旧版 API 中的 Drive.comment
换句话说,要另外设置。设置方式如下——
好,当我们设置完後,我们就可以取得 Comment 了!以下是我们这次 Comment 的资料——
那不罗唆,直接上程序码——
function readComments(){
let comments = Drive.Comments.list(target_slide_ID)
for(comment of comments.items){
Logger.log("Comment Content is : "+ comment.content)
Logger.log("Comment Anchor is : "+comment.anchor)
Logger.log("Comment Anchor page is : "+comment.anchor['page'])
Logger.log("Comment Anchor page is : "+JSON.parse(comment.anchor)['page'])
}
}
这段程序码执行起来长这样——
而输出的图放大在这边——
可以核对到 comment.content
读到的发现确实是我们要的 Comment 没错。但为什麽要对 comment.anchor
另外再取 JSON 呢?这边说明一下。comment.anchor
的意思是指,「这个 Comment 的锚⚓️」,也就是位在哪张 Slide 当中。但因为它原本 API 会让我们取得这样的资讯——
Logger.log(comment.anchor)
// {"type":"shape","uid":1632396166038,"page":"SLIDES_API791698242_104","targets":["SLIDES_API791698242_105"]}
Logger.log(comment.anchor['page'])
// null
明明是 Dict,却不让我们用 Dictionary 的取法,这是因为它现在在物件中这一整串不被理解为 Dictionary。需要另外再透过 JSON.parse()
把它变成我们可以读的 Dict。所以才会用这样的读法——
Logger.log(JSON.parse(comment.anchor)['page'])
// SLIDES_API791698242_96
所以最後我们能读到 Comment 和所在位置了,要怎麽结合起来?这边我们使用 {}
,也就是 Dictionary,它的好处是「提取」与「确认是否存在」上使用的时间相对其他资料结构检疫。但因为 Googel Apps Script 通常是小量做,所以相对时间与空间复杂度不用想太多。但对 Dict 不熟者可以参考 MDN 的介绍。
function readAndWriteCommentsWithDict(){
let comments = Drive.Comments.list(target_slide_ID)
let page_id_content={}
let update_time = new Date().toLocaleDateString();
for(comment of comments.items){
let page_content = comment.content;
let page_id = JSON.parse(comment.anchor)['page']
if ((page_id in page_id_content)){
page_id_content[page_id].push(page_content)
}else{
page_id_content[page_id] = [page_content]
}
}
let pres = SlidesApp.openById(target_slide_ID);
let slides = pres.getSlides();
let result = [];
for(let i = 0; i<slides.length; i++){
let slide = slides[i];
let slide_id = slide.getObjectId();
if (slide_id in page_id_content){
result.push([update_time, i+1, page_id_content[slide_id]])
}
}
Logger.log(result)
}
跑起来长这样——
好,那今天就是我们的结果了。
好,那今天就到这边。今天我们主要学了:
注意的是,今天第 2 点的「读 Comment」其实是 Google Drive 中的档案都可以用,但细节的程序码会需要再修正就是。
今天进入了 Slide 的最後一天,希望对大家有所帮助。如果还有问题,透过留言之外,也可以到 Facebook Group,想开很久这次铁人赛才真的开起来,欢迎来当 Founding Member。如果不想错过可以订阅按赞小铃铛(?),也欢迎留言跟我说你还想知道什麽做法/主题。我们明天见。
大家好我是乌木白,今天来向大家介绍GitHub,我自己很喜欢的一个可以做很多功能的网站!! 什麽是...
大家好 今天也来涂鸦献丑一下~ 本日想尝试一下阴影跟反光 今天目标是画一只类似章鱼但是却有拥有带刺壳...
前言 昨天我们完成了point简单的read 跟route model controll等 今天我们...
使用绝对定位 / 相对定位 设计版型 https://ithelp.ithome.com.tw/up...
▉A.17 Information Security Aspects Of Business营运持续...