{"id":707,"date":"2020-08-27T23:53:46","date_gmt":"2020-08-28T02:53:46","guid":{"rendered":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/?page_id=707"},"modified":"2020-08-28T00:08:21","modified_gmt":"2020-08-28T03:08:21","slug":"trabalhando-com-dados","status":"publish","type":"page","link":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/modulo-avancado\/aula-3-scripts-google\/trabalhando-com-dados\/","title":{"rendered":"Trabalhando com Dados"},"content":{"rendered":"<h3 class=\"step-title\">Configurando<\/h3>\n<p>Os exerc\u00edcios neste codelab requerem uma planilha para funcionar. Siga estas etapas para criar uma nova planilha para usar nestes exerc\u00edcios:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Crie uma nova planilha em seu Google Drive.\u00a0Voc\u00ea pode fazer isso na\u00a0<a href=\"https:\/\/drive.google.com\/drive\/my-drive\" target=\"_blank\" rel=\"noopener noreferrer\">interface<\/a>\u00a0do\u00a0<a href=\"https:\/\/drive.google.com\/drive\/my-drive\" target=\"_blank\" rel=\"noopener noreferrer\">Drive<\/a>\u00a0selecionando\u00a0Novo&gt; Planilhas Google\u00a0.\u00a0A nova planilha \u00e9 colocada em seu Drive raiz por padr\u00e3o.<\/li>\n<li>Clique no t\u00edtulo da planilha e altere de &#8220;Planilha sem t\u00edtulo&#8221; para &#8220;Manipula\u00e7\u00e3o de dados e menus personalizados&#8221;.\u00a0Sua planilha deve ser semelhante a esta:<\/li>\n<\/ol>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/545c02912de7d112.png\" width=\"831\" height=\"362\" \/><\/p>\n<p class=\"image-container\">\n<ol start=\"3\" type=\"1\">\n<li>Selecione\u00a0Ferramentas&gt; Editor de scripts\u00a0para abrir o editor de scripts.<\/li>\n<li>Clique no t\u00edtulo do projeto e altere-o de &#8220;Projeto sem t\u00edtulo&#8221; para &#8220;Manipula\u00e7\u00e3o de dados e menus personalizados&#8221;.\u00a0Clique em\u00a0OK\u00a0para salvar a altera\u00e7\u00e3o do t\u00edtulo:<\/li>\n<\/ol>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/f744919a4905f9d6.png\" width=\"827\" height=\"254\" \/><\/p>\n<p class=\"image-container\">\n<p>\u00a0 \u00a0 Com uma planilha e um projeto em branco, voc\u00ea est\u00e1 pronto para iniciar o laborat\u00f3rio!\u00a0Passe para a pr\u00f3xima se\u00e7\u00e3o para come\u00e7ar a aprender sobre os menus personalizados.<\/p>\n<p>&nbsp;<\/p>\n<p>Observa\u00e7\u00e3o:\u00a0se voc\u00ea estiver usando uma\u00a0conta\u00a0<a href=\"http:\/\/gmail.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">gmail.com<\/a>\u00a0, poder\u00e1 ver uma caixa de di\u00e1logo &#8220;Este aplicativo n\u00e3o foi verificado&#8221; ao usar o script pela primeira vez.\u00a0O Google usa isso para avisar os usu\u00e1rios que podem estar usando c\u00f3digo de autores desconhecidos ou n\u00e3o confi\u00e1veis.\u00a0Se voc\u00ea vir esta caixa de di\u00e1logo, n\u00e3o h\u00e1 problema em continuar, pois voc\u00ea \u00e9 o autor do script.\u00a0Nesses casos, continue autorizando o script fazendo o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Na caixa de di\u00e1logo &#8220;Este aplicativo n\u00e3o foi verificado&#8221;, clique em\u00a0Avan\u00e7ado\u00a0.<\/li>\n<li>Clique em\u00a0Ir para manipula\u00e7\u00e3o de dados e menus personalizados (inseguro).<\/li>\n<li>Na pr\u00f3xima tela, clique em\u00a0Permitir\u00a0.<\/li>\n<\/ol>\n<p>Ao longo deste codelab, voc\u00ea pode ver v\u00e1rios prompts de permiss\u00e3o.\u00a0Siga as instru\u00e7\u00f5es na tela para continuar autorizando o c\u00f3digo.\u00a0Voc\u00ea pode ler mais sobre esse processo no\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/services\/authorization\" target=\"_blank\" rel=\"noopener noreferrer\">guia de autoriza\u00e7\u00e3o<\/a>\u00a0do\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/services\/authorization\" target=\"_blank\" rel=\"noopener noreferrer\">Apps Script<\/a>\u00a0.<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Vis\u00e3o\u00a0geral: importar dados com um item de menu personalizado<\/h3>\n<p>O Apps Script oferece a capacidade de definir\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/menus\" target=\"_blank\" rel=\"noopener noreferrer\">menus personalizados<\/a>\u00a0que podem aparecer no Planilhas Google.\u00a0Voc\u00ea tamb\u00e9m pode usar menus personalizados no Google Docs, Google Slides e Google Forms.\u00a0Ao definir um item de menu personalizado, voc\u00ea cria um r\u00f3tulo de texto e o conecta a uma fun\u00e7\u00e3o do Apps Script em seu projeto de script.\u00a0Quando voc\u00ea adiciona o menu \u00e0 IU, ele aparece no Planilhas Google:<\/p>\n<p class=\"image-container\"><img title=\"Exemplo de menu personalizado do Planilhas\" src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/d6b694da6b8c6783.png\" width=\"820\" height=\"137\" \/><\/p>\n<p>\u00a0 \u00a0 Quando um usu\u00e1rio clica em um item de menu personalizado, a fun\u00e7\u00e3o do Apps Script associada a ele \u00e9 executada.\u00a0Esta \u00e9 uma maneira pr\u00e1tica de fazer com que as fun\u00e7\u00f5es do Apps Script sejam executadas sem ter que abrir o editor de script.\u00a0Ele tamb\u00e9m permite que outros usu\u00e1rios da planilha executem seu c\u00f3digo sem precisar saber nada sobre como ele ou o Apps Script funcionam &#8211; para eles, \u00e9 apenas mais um item de menu.<\/p>\n<p>Os itens de menu personalizados s\u00e3o definidos na\u00a0fun\u00e7\u00e3o de\u00a0<em>gatilho simples<\/em>\u00a0, sobre a qual voc\u00ea aprender\u00e1 na pr\u00f3xima se\u00e7\u00e3o.<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\"><code>onOpen()<\/code><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">A fun\u00e7\u00e3o onOpen ()<\/h3>\n<p><em>\u00a0 \u00a0\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\" target=\"_blank\" rel=\"noopener noreferrer\">Os gatilhos<\/a><\/em>\u00a0no Apps Script fornecem uma maneira de executar c\u00f3digos espec\u00edficos do Apps Script em resposta a condi\u00e7\u00f5es ou eventos espec\u00edficos.\u00a0Ao criar um gatilho, voc\u00ea define qual evento faz com que o gatilho seja disparado e fornece uma fun\u00e7\u00e3o do Apps Script que \u00e9 executada quando esse evento acontece.<\/p>\n<p><code><a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\">onOpen()<\/a><\/code>\u00e9 um exemplo de\u00a0<em>gatilho simples<\/em>\u00a0.\u00a0Gatilhos simples s\u00e3o f\u00e1ceis de configurar &#8211; tudo o que voc\u00ea precisa fazer \u00e9 escrever uma fun\u00e7\u00e3o do Apps Script chamada\u00a0<code>onOpen()<\/code>\u00a0e o Apps Script a executar\u00e1 sempre que a planilha associada for aberta ou recarregada:<\/p>\n<pre><code><span class=\"com\">\/**\r\n * A special function that runs when the spreadsheet is first\r\n * opened or reloaded. onOpen() is used to add custom menu\r\n * items to the spreadsheet.\r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> onOpen<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">{<\/span>\r\n <span class=\"com\">\/* ... *\/<\/span> \r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Conceito-chave\u00a0: gatilhos simples s\u00e3o f\u00e1ceis de configurar e usar, mas t\u00eam v\u00e1rias\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#restrictions\" target=\"_blank\" rel=\"noopener noreferrer\">restri\u00e7\u00f5es<\/a>\u00a0.\u00a0Devido a essas limita\u00e7\u00f5es,\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\"><code>onOpen()<\/code><\/a>\u00a0\u00e9 usado apenas para criar itens de menu.<\/p>\n<p>Os gatilhos s\u00e3o um t\u00f3pico complexo e, como tal, est\u00e3o al\u00e9m do escopo deste codelab.\u00a0Por enquanto, voc\u00ea pode apenas pensar\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\"><code>onOpen()<\/code><\/a>\u00a0em um manipulador de eventos que adiciona itens de menu sempre que voc\u00ea carrega uma planilha.<\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Vamos criar um menu personalizado!<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Substitua o c\u00f3digo em seu projeto de script pelo seguinte:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/**\r\n * A special function that runs when the spreadsheet is first\r\n * opened or reloaded. onOpen() is used to add custom menu\r\n * items to the spreadsheet.\r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> onOpen<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">{<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> ui <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getUi<\/span><span class=\"pun\">();<\/span><span class=\"pln\">\r\n  ui<\/span><span class=\"pun\">.<\/span><span class=\"pln\">createMenu<\/span><span class=\"pun\">(<\/span><span class=\"str\">'Book-list'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addItem<\/span><span class=\"pun\">(<\/span><span class=\"str\">'Load Book-list'<\/span><span class=\"pun\">,<\/span> <span class=\"str\">'loadBookList'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addToUi<\/span><span class=\"pun\">();<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Vamos revisar este c\u00f3digo para entender como ele funciona.\u00a0Em\u00a0<code>onOpen()<\/code>, a primeira linha usa o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/spreadsheet-app#getui\" target=\"_blank\" rel=\"noopener noreferrer\"><code>getUi()<\/code><\/a>\u00a0m\u00e9todo para adquirir um\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/ui.html\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Ui<\/code><\/a>\u00a0objeto que representa a interface do usu\u00e1rio da planilha ativa \u00e0 qual este script est\u00e1 vinculado.<\/p>\n<p>As pr\u00f3ximas tr\u00eas linhas criam um novo menu (\u00a0<code>Book-list<\/code>), adiciona um item de menu (\u00a0<code>Load Book-list<\/code>) a esse menu e, em seguida, adiciona o menu \u00e0 interface da planilha.\u00a0Isto \u00e9 feito com as\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/ui#createmenucaption\" target=\"_blank\" rel=\"noopener noreferrer\"><code>createMenu(caption)<\/code><\/a>,\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/menu#addItem(String,String)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>addItem(caption, functionName)<\/code><\/a>\u00a0e\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/menu#addtoui\" target=\"_blank\" rel=\"noopener noreferrer\"><code>addToUi()<\/code><\/a>m\u00e9todos, respectivamente.<\/p>\n<p>O\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/menu#addItem(String,String)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>addItem(caption, functionName)<\/code><\/a>\u00a0cria uma conex\u00e3o entre o r\u00f3tulo do item de menu e uma fun\u00e7\u00e3o Apps Script que \u00e9 executada quando esse item de menu \u00e9 selecionado.\u00a0Nesse caso, a sele\u00e7\u00e3o do\u00a0<code>Load Book-list<\/code>\u00a0item de menu faz com que o Planilhas tente executar a\u00a0<code>loadBookList()<\/code>\u00a0fun\u00e7\u00e3o (que ainda n\u00e3o existe).<\/p>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Vamos executar esta fun\u00e7\u00e3o agora para ver se funciona!\u00a0Fa\u00e7a o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>No Planilhas Google, recarregue sua planilha.\u00a0Nota: isso geralmente fecha a guia com seu editor de script.<\/li>\n<li>Reabra seu editor de script selecionando\u00a0Ferramentas&gt; Editor de script\u00a0.<\/li>\n<\/ol>\n<p>Depois que a planilha for recarregada, voc\u00ea ver\u00e1 um novo menu chamado\u00a0<code>Book-list<\/code>\u00a0deve aparecer na barra de menus:<\/p>\n<p class=\"image-container\"><img title=\"Menu personalizado: lista de livros\" src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/687dfb214f2930ba.png\" width=\"827\" height=\"95\" \/><\/p>\n<p>\u00a0 \u00a0 Ao clicar\u00a0na lista de livros\u00a0, voc\u00ea pode ver o menu suspenso resultante:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/8a4a391fbabcb16a.png\" width=\"836\" height=\"87\" \/><\/p>\n<p>\u00a0 \u00a0 E \u00e9 assim que voc\u00ea pode criar seu pr\u00f3prio menu personalizado no Planilhas!\u00a0A pr\u00f3xima se\u00e7\u00e3o define a\u00a0<code>loadBookList()<\/code>\u00a0fun\u00e7\u00e3o e apresenta uma maneira de interagir com os dados no Apps Script: lendo outras planilhas.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Importando dados da planilha<\/p>\n<p>Agora que criou um menu personalizado, voc\u00ea pode criar fun\u00e7\u00f5es que podem ser executadas apenas clicando no pr\u00f3prio item de menu.<\/p>\n<p>No momento, o menu personalizado\u00a0<code>Book-list<\/code>\u00a0tem um item de menu:\u00a0<code>Load Book-list.<\/code>\u00a0Mas, a fun\u00e7\u00e3o chamada quando voc\u00ea escolhe o\u00a0<code>Load Book-list<\/code>\u00a0item de menu\u00a0<code>loadBookList(),<\/code>\u00a0n\u00e3o existe em seu script, portanto, selecionar\u00a0Lista de livros&gt; Carregar lista de livros\u00a0gera um erro:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/b94dcef066e7041d.gif\" width=\"839\" height=\"131\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Voc\u00ea pode corrigir esse erro implementando a\u00a0<code>loadBookList()<\/code>\u00a0fun\u00e7\u00e3o.<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Voc\u00ea deseja que o novo item de menu preencha a planilha com dados para trabalhar, ent\u00e3o implementar\u00e1\u00a0<code>loadBookList()<\/code>\u00a0para ler dados de outra planilha e copi\u00e1-los para esta:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Adicione o seguinte c\u00f3digo ao seu script em\u00a0<code>onOpen()<\/code>:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/** \r\n * Creates a template book list based off of the\r\n * provided 'codelab-book-list' sheet.\r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> loadBookList<\/span><span class=\"pun\">(){<\/span>\r\n  <span class=\"com\">\/\/ Gets the active sheet.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> sheet <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getActiveSheet<\/span><span class=\"pun\">();<\/span>\r\n  \r\n  <span class=\"com\">\/\/ Gets a different spreadsheet from Drive via the<\/span>\r\n  <span class=\"com\">\/\/ spreadsheet's ID. <\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookSS <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">openById<\/span><span class=\"pun\">(<\/span>\r\n    <span class=\"str\">\"1c0GvbVUDeBmhTpq_A3vJh2xsebtLuwGwpBYqcOBqGvo\"<\/span> \r\n  <span class=\"pun\">);<\/span>\r\n\r\n  <span class=\"com\">\/\/ Gets the sheet, data range, and values of the<\/span>\r\n  <span class=\"com\">\/\/ spreadsheet stored in bookSS.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookSheet <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookSS<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getSheetByName<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"codelab-book-list\"<\/span><span class=\"pun\">);<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookRange <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookSheet<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getDataRange<\/span><span class=\"pun\">();<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookListValues <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getValues<\/span><span class=\"pun\">();<\/span>\r\n\r\n  <span class=\"com\">\/\/ Add those values to the active sheet in the current<\/span>\r\n  <span class=\"com\">\/\/ spreadsheet. This overwrites any values that already<\/span>\r\n  <span class=\"com\">\/\/ exist there. <\/span><span class=\"pln\">\r\n  sheet<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getRange<\/span><span class=\"pun\">(<\/span><span class=\"lit\">1<\/span><span class=\"pun\">,<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> bookRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getHeight<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> bookRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getWidth<\/span><span class=\"pun\">())<\/span> \r\n    <span class=\"pun\">.<\/span><span class=\"pln\">setValues<\/span><span class=\"pun\">(<\/span><span class=\"pln\">bookListValues<\/span><span class=\"pun\">);<\/span>\r\n  \r\n  <span class=\"com\">\/\/ Rename the destination sheet and resize the data<\/span>\r\n  <span class=\"com\">\/\/ columns for easier reading.<\/span><span class=\"pln\">\r\n  sheet<\/span><span class=\"pun\">.<\/span><span class=\"pln\">setName<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"Book-list\"<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\n  sheet<\/span><span class=\"pun\">.<\/span><span class=\"pln\">autoResizeColumns<\/span><span class=\"pun\">(<\/span><span class=\"lit\">1<\/span><span class=\"pun\">,<\/span> <span class=\"lit\">3<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Ent\u00e3o, como essa fun\u00e7\u00e3o funciona?\u00a0As\u00a0<code>loadBookList()<\/code>\u00a0utiliza\u00e7\u00f5es de fun\u00e7\u00e3o principalmente m\u00e9todos de as\u00a0<code>Spreadsheet<\/code>,\u00a0<code>Sheet<\/code>\u00a0e\u00a0<code>Range<\/code>\u00a0as classes que os codelabs anteriores introduzidas.\u00a0Com esses conceitos em mente, voc\u00ea pode dividir o\u00a0<code>loadBookList()<\/code>\u00a0c\u00f3digo nas quatro se\u00e7\u00f5es a seguir:<\/p>\n<h5>1: Identifique a folha de destino<\/h5>\n<p>A primeira linha usa\u00a0<code>SpreadsheetApp.getActiveSheet()<\/code>\u00a0para obter e armazenar uma refer\u00eancia ao objeto de pasta atual na vari\u00e1vel\u00a0<code>sheet<\/code>.\u00a0\u00c9 aqui que os dados ser\u00e3o copiados.<\/p>\n<h5>2: Identifique os dados de origem<\/h5>\n<p>As pr\u00f3ximas linhas estabelecem quatro vari\u00e1veis \u200b\u200bque se referem aos dados de origem que voc\u00ea est\u00e1 recuperando:<\/p>\n<ul>\n<li><code>bookSS<\/code>\u00a0armazena uma refer\u00eancia \u00e0 planilha da qual o c\u00f3digo est\u00e1 lendo os dados.\u00a0O c\u00f3digo encontra a planilha por seu\u00a0ID de planilha\u00a0.\u00a0Neste exemplo, fornecemos o ID de uma planilha de origem para leitura e abrimos a planilha usando o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/spreadsheet-app#openById(id)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>SpreadsheetApp.openById(id)<\/code><\/a>\u00a0m\u00e9todo.<\/li>\n<li><code>bookSheet<\/code>\u00a0armazena uma refer\u00eancia a uma planilha\u00a0<code>bookSS<\/code>\u00a0que cont\u00e9m os dados desejados.\u00a0O c\u00f3digo identifica a folha a ser lida por seu nome\u00a0<code>codelab-book-list<\/code>.<\/li>\n<li><code>bookRange<\/code>\u00a0armazena uma refer\u00eancia a um intervalo de dados em\u00a0<code>bookSheet<\/code>.\u00a0O m\u00e9todo\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/sheet#getDataRange()\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Sheet.getDataRange()<\/code><\/a>\u00a0retorna o intervalo contendo todas as c\u00e9lulas n\u00e3o vazias na planilha.\u00a0\u00c9 uma maneira pr\u00e1tica de garantir que voc\u00ea obtenha um intervalo que cubra todos os dados de uma planilha sem incluir muitas linhas e colunas vazias.<\/li>\n<li><code>bookListValues<\/code>\u00a0\u00e9 uma matriz 2D que cont\u00e9m todos os valores retirados das c\u00e9lulas em\u00a0<code>bookRange<\/code>.\u00a0O\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#getValues()\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.getValues()<\/code><\/a>\u00a0m\u00e9todo gera essa matriz lendo dados da planilha de origem.<\/li>\n<\/ul>\n<h5>3: Copie os dados da origem ao destino<\/h5>\n<p>A pr\u00f3xima se\u00e7\u00e3o de c\u00f3digo copia os\u00a0<code>bookListValues<\/code>\u00a0dados\u00a0<code>sheet<\/code>\u00a0e renomeia a planilha tamb\u00e9m:<\/p>\n<ul>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/sheet#getRange(Integer,Integer,Integer,Integer)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Sheet.getRange(row, column, numRows, numColumns)<\/code><\/a>\u00a0\u00e9 usado para identificar onde copiar os dados\u00a0<code>sheet<\/code>.<\/li>\n<li>Os\u00a0m\u00e9todos\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#getheight\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.getHeight()<\/code><\/a>\u00a0e\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#getwidth\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.getWidth()<\/code><\/a>\u00a0s\u00e3o usados \u200b\u200bpara medir o tamanho dos dados e definir um intervalo de destino das mesmas dimens\u00f5es.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setValues(Object)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValues(values)<\/code><\/a>\u00a0copia o array 2D\u00a0<code>bookListValues<\/code>\u00a0para o intervalo de destino, substituindo todos os dados j\u00e1 existentes.<\/li>\n<\/ul>\n<h5>4: Formate a folha de destino<\/h5>\n<p>O\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/sheet#setName(String)\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Sheet.setName(name)<\/code><\/a>\u00a0\u00e9 usado para alterar o nome da folha de destino para\u00a0<code>Book-list<\/code>.\u00a0A \u00faltima linha na fun\u00e7\u00e3o \u00e9 usada\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/sheet#autoresizecolumnsstartcolumn,-numcolumns\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Sheet.autoResizeColumns(startColumn, numColumns)<\/code><\/a>\u00a0para redimensionar as tr\u00eas primeiras colunas na planilha de destino, permitindo que voc\u00ea leia os novos dados mais facilmente.<\/p>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Voc\u00ea pode ver essa fun\u00e7\u00e3o em a\u00e7\u00e3o!\u00a0No Planilhas Google, selecione\u00a0Lista de livros&gt; Carregar lista de livros\u00a0para executar a fun\u00e7\u00e3o de preencher sua planilha:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/3c797e1e2b9fe641.gif\" width=\"820\" height=\"697\" \/><\/p>\n<p>\u00a0 \u00a0 Agora voc\u00ea tem uma folha com uma lista de t\u00edtulos de livros, autores e n\u00fameros ISBN de 13 d\u00edgitos!\u00a0Na pr\u00f3xima se\u00e7\u00e3o, voc\u00ea aprender\u00e1 como modificar e atualizar os dados nesta lista de livros usando manipula\u00e7\u00f5es de strings e menus personalizados.<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Vis\u00e3o\u00a0geral:\u00a0limpeza de dados\u00a0da planilha<\/h3>\n<p>Agora voc\u00ea pode ver as informa\u00e7\u00f5es do livro em sua planilha.\u00a0Cada linha se refere a um livro espec\u00edfico, listando seu t\u00edtulo, autor e n\u00famero ISBN em colunas separadas.\u00a0No entanto, voc\u00ea tamb\u00e9m pode ver alguns problemas com esses dados brutos:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Para algumas linhas, o t\u00edtulo e o autor s\u00e3o colocados juntos na coluna do t\u00edtulo, ligados por uma v\u00edrgula ou pela string &#8220;por&#8221;.<\/li>\n<li>Algumas linhas n\u00e3o cont\u00eam informa\u00e7\u00f5es sobre os t\u00edtulos e autores dos livros.<\/li>\n<\/ol>\n<p>pr\u00f3ximas se\u00e7\u00f5es, voc\u00ea corrigir\u00e1 esses problemas limpando os dados.\u00a0Para a primeira edi\u00e7\u00e3o, voc\u00ea criar\u00e1 fun\u00e7\u00f5es que leem a coluna do t\u00edtulo e dividem o texto sempre que uma v\u00edrgula ou delimitador &#8220;por&#8221; for encontrada, colocando o autor e as substrings de t\u00edtulo correspondentes nas colunas corretas.\u00a0Para o segundo problema, voc\u00ea escrever\u00e1 um c\u00f3digo que procura automaticamente as informa\u00e7\u00f5es do livro ausentes usando uma API externa e preenche essas informa\u00e7\u00f5es em sua planilha.<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Adicionando itens de menu<\/h3>\n<p>Voc\u00ea desejar\u00e1 criar tr\u00eas novos itens de menu para controlar as opera\u00e7\u00f5es de\u00a0limpeza de dados\u00a0que implementar\u00e1.<\/p>\n<p>&nbsp;<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Vamos atualizar\u00a0<code>onOpen()<\/code>\u00a0para incluir os itens de menu extras de que voc\u00ea precisa.\u00a0Fa\u00e7a o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Em seu projeto de script, atualize seu\u00a0<code>onOpen()<\/code>\u00a0c\u00f3digo para corresponder ao seguinte:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/**\r\n * A special function that runs when the spreadsheet is first\r\n * opened or reloaded. onOpen() is usually used to add custom\r\n * menu items to the spreadsheet.\r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> onOpen<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">{<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> ui <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getUi<\/span><span class=\"pun\">();<\/span><span class=\"pln\">\r\n  ui<\/span><span class=\"pun\">.<\/span><span class=\"pln\">createMenu<\/span><span class=\"pun\">(<\/span><span class=\"str\">'Book-list'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addItem<\/span><span class=\"pun\">(<\/span><span class=\"str\">'Load Book-list'<\/span><span class=\"pun\">,<\/span> <span class=\"str\">'loadBookList'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addSeparator<\/span><span class=\"pun\">()<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addItem<\/span><span class=\"pun\">(<\/span>\r\n      <span class=\"str\">'Separate title\/author at first comma'<\/span><span class=\"pun\">,<\/span> <span class=\"str\">'splitAtFirstComma'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addItem<\/span><span class=\"pun\">(<\/span>\r\n      <span class=\"str\">'Separate title\/author at last \"by\"'<\/span><span class=\"pun\">,<\/span> <span class=\"str\">'splitAtLastBy'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addSeparator<\/span><span class=\"pun\">()<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addItem<\/span><span class=\"pun\">(<\/span>\r\n      <span class=\"str\">'Fill in blank titles and author cells'<\/span><span class=\"pun\">,<\/span> <span class=\"str\">'fillInTheBlanks'<\/span><span class=\"pun\">)<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">addToUi<\/span><span class=\"pun\">();<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<li>No editor de script, selecione\u00a0<code>onOpen<\/code>\u00a0no menu suspenso da barra de tarefas e clique no\u00a0<img title=\"Corre\" src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/520b3b8ae24db874.png\" \/>bot\u00e3o.\u00a0Isso ser\u00e1 executado\u00a0<code>onOpen()<\/code>\u00a0para reconstruir o menu da planilha, para que voc\u00ea n\u00e3o precise recarregar a planilha.<\/li>\n<\/ol>\n<p>Neste novo c\u00f3digo, o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/base\/menu#addseparator\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Menu.addSeparator()<\/code><\/a>\u00a0m\u00e9todo cria um divisor horizontal no menu suspenso para que voc\u00ea possa manter grupos de itens de menu relacionados visualmente organizados.\u00a0Os novos itens de menu s\u00e3o ent\u00e3o adicionadas abaixo dela, com os r\u00f3tulos\u00a0<code>Separate title\/author at first comma<\/code>,\u00a0<code>Separate title\/author at last \"by\"<\/code>e\u00a0<code>Fill in blank titles and author cells<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">Observa\u00e7\u00e3o\u00a0: os itens de menu adicionados ser\u00e3o exibidos no Planilhas na mesma ordem em que voc\u00ea os adicionar ao\u00a0<code>onOpen()<\/code>\u00a0c\u00f3digo.<\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Em sua planilha, voc\u00ea pode clicar no\u00a0<code>Book-list<\/code>\u00a0menu para ver os novos itens de menu:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/580c806ce8fd4872.png\" width=\"836\" height=\"230\" \/><\/p>\n<p>\u00a0 \u00a0 Clicar nesses itens agora causar\u00e1 um erro, pois voc\u00ea ainda n\u00e3o implementou suas fun\u00e7\u00f5es correspondentes, ent\u00e3o vamos fazer isso a seguir.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Divis\u00e3o de texto em delimitadores de v\u00edrgula<\/h3>\n<p>O conjunto de dados que voc\u00ea importou para sua planilha tem algumas c\u00e9lulas em que o autor e o t\u00edtulo est\u00e3o combinados incorretamente em uma c\u00e9lula usando uma v\u00edrgula:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/ca91c43c4e51d6b5.png\" width=\"831\" height=\"403\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Dividir strings de texto em colunas separadas \u00e9 uma tarefa comum em planilhas.\u00a0O Planilhas Google oferece uma\u00a0<a href=\"https:\/\/support.google.com\/docs\/answer\/3094136\" target=\"_blank\" rel=\"noopener noreferrer\"><code>SPLIT()<\/code><\/a>\u00a0fun\u00e7\u00e3o que divide as strings em colunas.\u00a0No entanto, geralmente os conjuntos de dados apresentam problemas que n\u00e3o podem ser facilmente resolvidos com as fun\u00e7\u00f5es do Planilhas.\u00a0Nesses casos, voc\u00ea pode escrever o c\u00f3digo do Apps Script para realizar as opera\u00e7\u00f5es complexas necess\u00e1rias para limpar e organizar seus dados.<\/p>\n<p>Voc\u00ea come\u00e7a a limpar seus dados implementando primeiro uma fun\u00e7\u00e3o chamada\u00a0<code>splitAtFirstComma()<\/code>\u00a0que divide o autor e o t\u00edtulo em suas respectivas c\u00e9lulas quando v\u00edrgulas s\u00e3o encontradas.<\/p>\n<p>A\u00a0<code>splitAtFirstComma()<\/code>\u00a0fun\u00e7\u00e3o deve seguir as seguintes etapas:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Obtenha o intervalo que representa as c\u00e9lulas atualmente selecionadas.<\/li>\n<li>Verifique se as c\u00e9lulas nesse intervalo possuem uma v\u00edrgula.<\/li>\n<li>Onde forem encontradas v\u00edrgulas, divida a string em duas (e apenas duas) substrings no local da primeira v\u00edrgula.\u00a0Para tornar as coisas mais simples, voc\u00ea pode assumir que qualquer v\u00edrgula indica um\u00a0padr\u00e3o de string\u00a0&#8221;\u00a0<em>[autores], [t\u00edtulo]<\/em>\u00a0&#8220;.\u00a0Voc\u00ea tamb\u00e9m pode assumir que, se v\u00e1rias v\u00edrgulas aparecerem na c\u00e9lula, \u00e9 apropriado dividir na primeira v\u00edrgula da string.<\/li>\n<li>Defina as substrings como o novo conte\u00fado das respectivas c\u00e9lulas de t\u00edtulo e autor.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Para implementar essas etapas, voc\u00ea usar\u00e1 os mesmos\u00a0m\u00e9todos de\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/\" target=\"_blank\" rel=\"noopener noreferrer\">servi\u00e7o de planilha<\/a>\u00a0usados \u200b\u200bantes, mas tamb\u00e9m precisar\u00e1 usar um JavaScript simples para manipular os dados da string.\u00a0Execute as seguintes etapas:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>No editor do Apps Script, adicione a seguinte fun\u00e7\u00e3o ao final do seu projeto de script:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/** \r\n * Reformats title and author columns by splitting the title column\r\n * at the first comma, if present. \r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> splitAtFirstComma<\/span><span class=\"pun\">(){<\/span>\r\n  <span class=\"com\">\/\/ Get the active (currently highlighted) range.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> activeRange <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getActiveRange<\/span><span class=\"pun\">();<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> titleAuthorRange <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">offset<\/span><span class=\"pun\">(<\/span>\r\n    <span class=\"lit\">0<\/span><span class=\"pun\">,<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getHeight<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getWidth<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">+<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">);<\/span>\r\n\r\n  <span class=\"com\">\/\/ Get the current values of the selected title column cells.<\/span>\r\n  <span class=\"com\">\/\/ This is a 2D array.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> titleAuthorValues <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> titleAuthorRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getValues<\/span><span class=\"pun\">();<\/span>\r\n\r\n  <span class=\"com\">\/\/ Update values where commas are found. Assumes the presence<\/span>\r\n  <span class=\"com\">\/\/ of a comma indicates an \"authors, title\" pattern.<\/span>\r\n  <span class=\"kwd\">for<\/span> <span class=\"pun\">(<\/span><span class=\"kwd\">var<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> titleAuthorValues<\/span><span class=\"pun\">.<\/span><span class=\"pln\">length<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row<\/span><span class=\"pun\">++){<\/span>\r\n    <span class=\"kwd\">var<\/span><span class=\"pln\"> indexOfFirstComma <\/span><span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">].<\/span><span class=\"pln\">indexOf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\", \"<\/span><span class=\"pun\">);<\/span>\r\n\r\n    <span class=\"kwd\">if<\/span><span class=\"pun\">(<\/span><span class=\"pln\">indexOfFirstComma <\/span><span class=\"pun\">&gt;=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">){<\/span>\r\n      <span class=\"com\">\/\/ Found a comma, so split and update the values in<\/span>\r\n      <span class=\"com\">\/\/ the values array.<\/span>\r\n      <span class=\"kwd\">var<\/span><span class=\"pln\"> titlesAndAuthors <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">];<\/span>\r\n      \r\n      <span class=\"com\">\/\/ Update the title value in the array.<\/span><span class=\"pln\">\r\n      titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titlesAndAuthors<\/span><span class=\"pun\">.<\/span><span class=\"pln\">slice<\/span><span class=\"pun\">(<\/span><span class=\"pln\">indexOfFirstComma <\/span><span class=\"pun\">+<\/span> <span class=\"lit\">2<\/span><span class=\"pun\">);<\/span>\r\n      \r\n      <span class=\"com\">\/\/ Update the author value in the array.<\/span><span class=\"pln\">\r\n      titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">1<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titlesAndAuthors<\/span><span class=\"pun\">.<\/span><span class=\"pln\">slice<\/span><span class=\"pun\">(<\/span><span class=\"lit\">0<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> indexOfFirstComma<\/span><span class=\"pun\">);<\/span>\r\n    <span class=\"pun\">}<\/span>\r\n  <span class=\"pun\">}<\/span>\r\n\r\n\r\n  <span class=\"com\">\/\/ Put the updated values back into the spreadsheet.<\/span><span class=\"pln\">\r\n  titleAuthorRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">setValues<\/span><span class=\"pun\">(<\/span><span class=\"pln\">titleAuthorValues<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Vamos revisar o novo c\u00f3digo.\u00a0O c\u00f3digo consiste em tr\u00eas se\u00e7\u00f5es principais:<\/p>\n<h5>1: Recupere os valores do t\u00edtulo destacado<\/h5>\n<p>As tr\u00eas primeiras linhas estabelecem tr\u00eas vari\u00e1veis \u200b\u200bque se referem aos dados atuais na planilha:<\/p>\n<ul>\n<li><code>activeRange<\/code>\u00a0representa o intervalo que o usu\u00e1rio destacou no momento quando a\u00a0<code>splitAtFirstComma()<\/code>\u00a0fun\u00e7\u00e3o foi chamada.\u00a0Para simplificar este exerc\u00edcio, podemos assumir que o usu\u00e1rio s\u00f3 faz isso ao destacar c\u00e9lulas na coluna A.<\/li>\n<li><code>titleAuthorRange<\/code>\u00a0representa um novo intervalo que cobre as mesmas c\u00e9lulas\u00a0<code>activeRange<\/code>, mas tamb\u00e9m inclui mais uma coluna \u00e0 direita.\u00a0<code>titleAuthorRange<\/code>\u00a0\u00e9 criado usando o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#offsetrowoffset,-columnoffset,-numrows,-numcolumns\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.offset(rowOffset, columnOffset, numRows, numColumns)<\/code><\/a>\u00a0m\u00e9todo.\u00a0O c\u00f3digo precisa desse intervalo expandido porque precisa de um lugar para colocar os autores descobertos que encontrar na coluna do t\u00edtulo.<\/li>\n<li><code>titleAuthorValues<\/code>\u00a0\u00e9 uma matriz 2D de dados que foram extra\u00eddos do\u00a0<code>titleAuthorRange<\/code>\u00a0uso\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#getValues()\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.getValues()<\/code><\/a>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h5>2: Examine cada t\u00edtulo e divida em qualquer delimitador de v\u00edrgula encontrado<\/h5>\n<p>A pr\u00f3xima se\u00e7\u00e3o examina os valores\u00a0<code>titleAuthorValues<\/code>para procurar v\u00edrgulas.\u00a0Um\u00a0<a href=\"https:\/\/www.w3schools.com\/js\/js_loop_for.asp\" target=\"_blank\" rel=\"noopener noreferrer\">loop<\/a>\u00a0for\u00a0<a href=\"https:\/\/www.w3schools.com\/js\/js_loop_for.asp\" target=\"_blank\" rel=\"noopener noreferrer\">JavaScript<\/a>\u00a0\u00e9 usado para examinar todos os valores na primeira coluna de\u00a0<code>titleAuthorValues<\/code>.\u00a0Quando uma substring de v\u00edrgula \u00e9 encontrada (\u00a0<code>\", \"<\/code>) com o\u00a0<a href=\"https:\/\/www.w3schools.com\/jsref\/jsref_indexof.asp\" target=\"_blank\" rel=\"noopener noreferrer\">m\u00e9todo indexOf () da String JavaScript<\/a>\u00a0, o c\u00f3digo faz o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>O valor da string da c\u00e9lula \u00e9 copiado para a\u00a0<code>titlesAndAuthors<\/code>vari\u00e1vel.<\/li>\n<li>A localiza\u00e7\u00e3o da v\u00edrgula \u00e9 determinada usando o\u00a0m\u00e9todo\u00a0<a href=\"https:\/\/www.w3schools.com\/jsref\/jsref_indexof.asp\" target=\"_blank\" rel=\"noopener noreferrer\">indexOf () da String JavaScript<\/a>\u00a0.<\/li>\n<li>O\u00a0m\u00e9todo\u00a0<a href=\"https:\/\/www.w3schools.com\/jsref\/jsref_slice_string.asp\" target=\"_blank\" rel=\"noopener noreferrer\">slice () de String JavaScript<\/a>\u00a0\u00e9 usado duas vezes para obter a substring antes do delimitador de v\u00edrgula e a substring depois do delimitador.<\/li>\n<li>As substrings s\u00e3o copiadas de volta para o array 2D titleAuthorValues, sobrescrevendo os valores existentes naquela posi\u00e7\u00e3o.\u00a0Como estamos assumindo um\u00a0padr\u00e3o\u00a0&#8221;\u00a0<em>[autores], [t\u00edtulo]<\/em>\u00a0&#8220;, a ordem das duas substrings \u00e9 invertida para colocar o t\u00edtulo na primeira coluna e os autores na segunda.<\/li>\n<\/ol>\n<p>Observa\u00e7\u00e3o: quando o c\u00f3digo n\u00e3o encontra uma v\u00edrgula, ele deixa os dados dessa linha inalterados.<\/p>\n<p>&nbsp;<\/p>\n<p>3: Copie os novos valores de volta para a planilha<\/p>\n<p>Depois que todos os valores da c\u00e9lula do t\u00edtulo foram examinados, a matriz 2D titleAuthorValues \u200b\u200batualizada \u00e9 copiada de volta para a planilha usando<\/p>\n<p>o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluesvalues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValues(values)<\/code><\/a>\u00a0m\u00e9todo.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Ponto-chave\u00a0: o c\u00f3digo poderia ter atualizado cada c\u00e9lula da planilha individualmente conforme encontrava cada v\u00edrgula, chamando\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluevalue\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValue(value)<\/code><\/a>\u00a0toda vez que uma c\u00e9lula precisava ser alterada.\u00a0No entanto, isso resultaria em um c\u00f3digo muito mais lento, pois cada\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluevalue\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValue(value)<\/code><\/a>\u00a0chamada requer comunica\u00e7\u00e3o com o servidor.<\/p>\n<p>Ao atualizar os dados do Planilhas, \u00e9 quase sempre melhor colocar os valores em uma matriz 2D primeiro, atualizar a matriz e, em seguida, enviar os dados de volta para a planilha com uma \u00fanica\u00a0chamada.\u00a0Dessa forma, voc\u00ea minimiza a quantidade de comunica\u00e7\u00e3o com o servidor que seu c\u00f3digo precisa fazer, acelerando seu c\u00f3digo.<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluesvalues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValues(values)<\/code><\/a><\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Agora voc\u00ea pode ver os efeitos da\u00a0<code>splitAtFirstComma()<\/code>\u00a0fun\u00e7\u00e3o em a\u00e7\u00e3o!\u00a0Tente execut\u00e1-lo selecionando o\u00a0item de menu\u00a0Separar t\u00edtulo \/ autor na primeira v\u00edrgula\u00a0ap\u00f3s selecionar &#8230;<\/p>\n<p>&#8230; uma c\u00e9lula:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/a24763b60b305376.gif\" width=\"836\" height=\"170\" \/><\/p>\n<p>\u00a0 \u00a0 &#8230; ou v\u00e1rias c\u00e9lulas:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/89c5c89b357d3713.gif\" width=\"837\" height=\"215\" \/><\/p>\n<p>&nbsp;<\/p>\n<aside class=\"warning\">\u00a0 \u00a0 Nota:\u00a0Voc\u00ea pode selecionar qualquer coluna de texto em sua planilha e usar esta fun\u00e7\u00e3o para procurar v\u00edrgulas e dividir o texto de acordo com as regras que voc\u00ea definiu.\u00a0Esteja ciente de que, se o c\u00f3digo encontrar um delimitador de v\u00edrgula, ele substituir\u00e1 a c\u00e9lula imediatamente \u00e0 direita do original.<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<p>Agora voc\u00ea construiu uma fun\u00e7\u00e3o do Apps Script que processa dados do Planilhas Google!\u00a0Em seguida, voc\u00ea implementar\u00e1 a segunda fun\u00e7\u00e3o divisora.<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Dividindo o texto em delimitadores &#8220;por&#8221;<\/h3>\n<p>Olhando novamente para os dados originais, voc\u00ea pode ver outro problema.\u00a0Assim como alguns dos dados formatam t\u00edtulos e autores em uma \u00fanica c\u00e9lula como\u00a0<em>&#8220;[autores], [t\u00edtulo]&#8221;,<\/em>\u00a0outras c\u00e9lulas formatam autor e t\u00edtulo como\u00a0<em>&#8220;[t\u00edtulo] por [autores]<\/em>\u00a0:\u00a0<em>&#8220;<\/em><\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/41f0dd5ac63b62f4.png\" width=\"825\" height=\"400\" \/><\/p>\n<h4><\/h4>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Voc\u00ea pode resolver este problema usando a mesma t\u00e9cnica usada na \u00faltima se\u00e7\u00e3o, criando uma nova fun\u00e7\u00e3o chamada\u00a0<code>splitAtLastBy()<\/code>.\u00a0Essa fun\u00e7\u00e3o tem uma fun\u00e7\u00e3o muito semelhante a\u00a0<code>splitAtFirstComma()<\/code>&#8211; a \u00fanica diferen\u00e7a real \u00e9 que ela est\u00e1 procurando um padr\u00e3o de texto ligeiramente diferente.\u00a0Implemente esta fun\u00e7\u00e3o fazendo o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>No editor do Apps Script, adicione a seguinte fun\u00e7\u00e3o ao final do seu projeto de script:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/** \r\n * Reformats title and author columns by splitting title column\r\n * at the last instance of the string \" by \".\r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> splitAtLastBy<\/span><span class=\"pun\">(){<\/span>\r\n  <span class=\"com\">\/\/ Get the active (currently highlighted) range.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> activeRange <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getActiveRange<\/span><span class=\"pun\">();<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> titleAuthorRange <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">offset<\/span><span class=\"pun\">(<\/span>\r\n    <span class=\"lit\">0<\/span><span class=\"pun\">,<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getHeight<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> activeRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getWidth<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">+<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">);<\/span>\r\n\r\n  <span class=\"com\">\/\/ Get the current values of the selected title column cells.<\/span>\r\n  <span class=\"com\">\/\/ This is a 2D array.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> titleAuthorValues <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> titleAuthorRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getValues<\/span><span class=\"pun\">();<\/span>\r\n\r\n  <span class=\"com\">\/\/ Update values where \" by \" substrings are found. Assumes<\/span>\r\n  <span class=\"com\">\/\/ the presence of a \" by \" indicates an \"title by authors\"<\/span>\r\n  <span class=\"com\">\/\/ pattern.<\/span>\r\n  <span class=\"kwd\">for<\/span><span class=\"pun\">(<\/span><span class=\"kwd\">var<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> titleAuthorValues<\/span><span class=\"pun\">.<\/span><span class=\"pln\">length<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row<\/span><span class=\"pun\">++){<\/span>\r\n    <span class=\"kwd\">var<\/span><span class=\"pln\"> indexOfLastBy <\/span><span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">].<\/span><span class=\"pln\">lastIndexOf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\" by \"<\/span><span class=\"pun\">);<\/span>\r\n    \r\n    <span class=\"kwd\">if<\/span><span class=\"pun\">(<\/span><span class=\"pln\">indexOfLastBy <\/span><span class=\"pun\">&gt;=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">){<\/span>\r\n      <span class=\"com\">\/\/ Found a \" by \", so split and update the values in<\/span>\r\n      <span class=\"com\">\/\/ our array.<\/span>\r\n      <span class=\"kwd\">var<\/span><span class=\"pln\"> titlesAndAuthors <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">];<\/span>\r\n      \r\n      <span class=\"com\">\/\/ Update the title value.<\/span><span class=\"pln\">\r\n      titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">0<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titlesAndAuthors<\/span><span class=\"pun\">.<\/span><span class=\"pln\">slice<\/span><span class=\"pun\">(<\/span><span class=\"lit\">0<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> indexOfLastBy<\/span><span class=\"pun\">);<\/span>\r\n      \r\n      <span class=\"com\">\/\/ Update the author value.<\/span><span class=\"pln\">\r\n      titleAuthorValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"lit\">1<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\">\r\n        titlesAndAuthors<\/span><span class=\"pun\">.<\/span><span class=\"pln\">slice<\/span><span class=\"pun\">(<\/span><span class=\"pln\">indexOfLastBy <\/span><span class=\"pun\">+<\/span> <span class=\"lit\">4<\/span><span class=\"pun\">);<\/span>\r\n    <span class=\"pun\">}<\/span>\r\n  <span class=\"pun\">}<\/span>\r\n\r\n  <span class=\"com\">\/\/ Put the values back into the spreadsheet.<\/span><span class=\"pln\">\r\n  titleAuthorRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">setValues<\/span><span class=\"pun\">(<\/span><span class=\"pln\">titleAuthorValues<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Existem algumas diferen\u00e7as importantes entre este c\u00f3digo e\u00a0<code>splitAtFirstComma()<\/code>:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>A substring &#8221;\u00a0<code>by<\/code>\u00a0&#8221; \u00e9 usada como um delimitador de string, em vez de &#8221;\u00a0<code>,<\/code>\u00a0&#8220;.<\/li>\n<li>Aqui, o JavaScript\u00a0<a href=\"https:\/\/www.w3schools.com\/jsref\/jsref_lastindexof.asp\" target=\"_blank\" rel=\"noopener noreferrer\"><code>String.lastIndexOf(substring)<\/code><\/a>\u00a0\u00e9 usado em vez de\u00a0<a href=\"https:\/\/www.w3schools.com\/jsref\/jsref_indexof.asp\" target=\"_blank\" rel=\"noopener noreferrer\"><code>String.indexOf(substring)<\/code><\/a>.\u00a0Isso significa que se houver v\u00e1rias\u00a0<code>by<\/code>\u00a0substrings\u00a0&#8221;\u00a0&#8221; na string inicial, todas, exceto o \u00faltimo &#8221;\u00a0<code>by<\/code>&#8220;, ser\u00e3o consideradas parte do t\u00edtulo.<\/li>\n<li>Depois de dividir a string, a primeira substring \u00e9 definida como o t\u00edtulo e a segunda como a string do autor (esta \u00e9 a ordem oposta \u00e0 usada\u00a0<code>splitAtFirstComma()<\/code>).<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Agora voc\u00ea pode ver os efeitos da\u00a0<code>splitAtLastBy()<\/code>\u00a0fun\u00e7\u00e3o em a\u00e7\u00e3o!\u00a0Tente execut\u00e1-lo selecionando o\u00a0item de menu\u00a0Separar t\u00edtulo \/ autor finalmente &#8220;por&#8221;\u00a0depois de selecionar &#8230;<\/p>\n<p>&#8230; uma c\u00e9lula:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/4e6679e134145975.gif\" width=\"842\" height=\"227\" \/><\/p>\n<p>\u00a0 \u00a0 &#8230; ou v\u00e1rias c\u00e9lulas:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/3c879c572c61e62f.gif\" width=\"838\" height=\"226\" \/><\/p>\n<p>\u00a0 \u00a0 Voc\u00ea concluiu esta se\u00e7\u00e3o do codelab.\u00a0Agora voc\u00ea pode usar o Apps Script para ler e modificar os dados da string em uma planilha e usar menus personalizados para executar diferentes comandos do Apps Script!<\/p>\n<p>Na pr\u00f3xima se\u00e7\u00e3o, voc\u00ea aprender\u00e1 como melhorar ainda mais esse conjunto de dados, preenchendo as c\u00e9lulas em branco com dados extra\u00eddos de uma API p\u00fablica.<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Vis\u00e3o\u00a0geral: Obten\u00e7\u00e3o de dados de APIs p\u00fablicas<\/h3>\n<p>At\u00e9 agora, voc\u00ea refinou seu conjunto de dados para corrigir alguns problemas de\u00a0formata\u00e7\u00e3o\u00a0de t\u00edtulo e autor, mas o conjunto de dados ainda est\u00e1 faltando algumas informa\u00e7\u00f5es, destacadas nas c\u00e9lulas abaixo:<\/p>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/af0dba8cb09d1a49.png\" width=\"829\" height=\"251\" \/><\/p>\n<p>\u00a0 \u00a0 Os dados ausentes n\u00e3o podem ser obtidos por opera\u00e7\u00f5es de string nos dados que voc\u00ea tem aqui.\u00a0Em vez disso, voc\u00ea precisar\u00e1 obter os dados ausentes de outra fonte.\u00a0Nesse caso, voc\u00ea pode fazer isso no Apps Script solicitando informa\u00e7\u00f5es de uma\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/services\/external\" target=\"_blank\" rel=\"noopener noreferrer\">API externa<\/a>\u00a0que pode fornecer ao seu script informa\u00e7\u00f5es adicionais sobre o livro.<\/p>\n<p><em>\u00a0 \u00a0 APIs<\/em>\u00a0s\u00e3o\u00a0<em>interfaces de programa\u00e7\u00e3o de aplicativos<\/em>\u00a0.\u00a0\u00c9 um termo bastante\u00a0geral, mas basicamente significa que algu\u00e9m forneceu um servi\u00e7o que seus programas e scripts podem chamar para fazer coisas espec\u00edficas, como solicitar informa\u00e7\u00f5es ou realizar certas a\u00e7\u00f5es.\u00a0Nesta se\u00e7\u00e3o, voc\u00ea est\u00e1 chamando uma API dispon\u00edvel publicamente para solicitar informa\u00e7\u00f5es adicionais do livro, que voc\u00ea ent\u00e3o coloca nas c\u00e9lulas vazias de sua planilha.<\/p>\n<p>Esta se\u00e7\u00e3o ensina como:<\/p>\n<ul>\n<li>Solicite dados do livro de uma fonte de API externa.<\/li>\n<li>Extraia as informa\u00e7\u00f5es do t\u00edtulo e do autor dos dados retornados e grave essas informa\u00e7\u00f5es em sua planilha.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Buscando dados externos com UrlFetch<\/h3>\n<p>Antes de se aprofundar no c\u00f3digo que funciona diretamente com sua planilha, voc\u00ea pode aprender sobre as especificidades de trabalhar com APIs externas no Apps Script criando uma\u00a0fun\u00e7\u00e3o auxiliar\u00a0espec\u00edfica para\u00a0<a href=\"https:\/\/openlibrary.org\/dev\/docs\/api\/books\" target=\"_blank\" rel=\"noopener noreferrer\">solicitar informa\u00e7\u00f5es<\/a>\u00a0de\u00a0<a href=\"https:\/\/openlibrary.org\/developers\/api\" target=\"_blank\" rel=\"noopener noreferrer\">livros da API Open Library<\/a>\u00a0p\u00fablica\u00a0.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Nota:\u00a0<a href=\"https:\/\/openlibrary.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Open Library<\/a>\u00a0\u00e9 um arquivo da Internet que se esfor\u00e7a para criar uma p\u00e1gina da web para cada publica\u00e7\u00e3o de livro.\u00a0Se estiver interessado, voc\u00ea pode ler mais sobre a Open Library em seu\u00a0<a href=\"https:\/\/openlibrary.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">site oficial<\/a>\u00a0e sua\u00a0<a href=\"https:\/\/openlibrary.org\/developers\/api\" target=\"_blank\" rel=\"noopener noreferrer\">documenta\u00e7\u00e3o de API<\/a>\u00a0.<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<p>Essa fun\u00e7\u00e3o auxiliar\u00a0<code>fetchBookData_(ISBN)<\/code>\u00a0pega um n\u00famero ISBN de 13 d\u00edgitos de um livro como par\u00e2metro e retorna dados sobre esse livro conectando-se e recuperando informa\u00e7\u00f5es da\u00a0<a href=\"https:\/\/openlibrary.org\/developers\/api\" target=\"_blank\" rel=\"noopener noreferrer\">API Open Library<\/a>\u00a0e, em seguida,\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/services\/external#work_with_json\" target=\"_blank\" rel=\"noopener noreferrer\">analisando o objeto JSON retornado<\/a>\u00a0.<\/p>\n<p>&nbsp;<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Implemente essa fun\u00e7\u00e3o auxiliar fazendo o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>No editor do Apps Script, adicione o seguinte c\u00f3digo ao final do seu script:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/*\r\n * Helper function that retrieves book data from the Open Library\r\n * public API.\r\n *\r\n * @param {number} ISBN - The ISBN number of the book to look up.\r\n * @return {object} The book's data, in JSON format. \r\n *\/<\/span>\r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> fetchBookData_<\/span><span class=\"pun\">(<\/span><span class=\"pln\">ISBN<\/span><span class=\"pun\">){<\/span>\r\n  <span class=\"com\">\/\/ Connect to the public API.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> url <\/span><span class=\"pun\">=<\/span> <span class=\"str\">\"https:\/\/openlibrary.org\/api\/books?bibkeys=ISBN:\"<\/span>\r\n      <span class=\"pun\">+<\/span><span class=\"pln\"> ISBN <\/span><span class=\"pun\">+<\/span> <span class=\"str\">\"&amp;jscmd=details&amp;format=json\"<\/span><span class=\"pun\">;<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> response <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">UrlFetchApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">fetch<\/span><span class=\"pun\">(<\/span><span class=\"pln\">\r\n      url<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">{<\/span><span class=\"str\">'muteHttpExceptions'<\/span><span class=\"pun\">:<\/span> <span class=\"kwd\">true<\/span><span class=\"pun\">});<\/span>\r\n  \r\n  <span class=\"com\">\/\/ Make request to API and get response before this point.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> json <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> response<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getContentText<\/span><span class=\"pun\">();<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookData <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> JSON<\/span><span class=\"pun\">.<\/span><span class=\"pln\">parse<\/span><span class=\"pun\">(<\/span><span class=\"pln\">json<\/span><span class=\"pun\">);<\/span> \r\n  \r\n  <span class=\"com\">\/\/ Return only the data we're interested in. <\/span>\r\n  <span class=\"kwd\">return<\/span><span class=\"pln\"> bookData<\/span><span class=\"pun\">[<\/span><span class=\"str\">'ISBN:'<\/span> <span class=\"pun\">+<\/span><span class=\"pln\"> ISBN<\/span><span class=\"pun\">];<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Observa\u00e7\u00e3o:\u00a0no Apps Script, as fun\u00e7\u00f5es com nomes terminados em &#8220;_&#8221; s\u00e3o consideradas\u00a0<em>privadas<\/em>\u00a0.\u00a0Essas fun\u00e7\u00f5es n\u00e3o podem ser chamadas por outros scripts, se presentes em uma\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/libraries\" target=\"_blank\" rel=\"noopener noreferrer\">biblioteca<\/a>\u00a0, ou por clientes durante\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/html\/communication\" target=\"_blank\" rel=\"noopener noreferrer\">a comunica\u00e7\u00e3o servidor-cliente<\/a>\u00a0.\u00a0Esses s\u00e3o t\u00f3picos avan\u00e7ados, portanto, por enquanto, apenas saiba que \u00e9 uma pr\u00e1tica recomendada terminar o nome de uma fun\u00e7\u00e3o em &#8220;_&#8221; se for uma fun\u00e7\u00e3o auxiliar que apenas o script atual precisar\u00e1 usar.<\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Este c\u00f3digo \u00e9 dividido em duas se\u00e7\u00f5es principais:<\/p>\n<p>&nbsp;<\/p>\n<h5>1: Fazendo uma solicita\u00e7\u00e3o de API<\/h5>\n<p>Nas duas primeiras linhas\u00a0<code>fetchBookData_(ISBN)<\/code>\u00a0conecta-se \u00e0\u00a0<a href=\"https:\/\/openlibrary.org\/developers\/api\" target=\"_blank\" rel=\"noopener noreferrer\">API Open Library<\/a>\u00a0p\u00fablica\u00a0, usando o endpoint de URL da API e o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">servi\u00e7o\u00a0<\/a><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">UrlFetch<\/a>\u00a0do Apps Script\u00a0.<\/p>\n<p>A\u00a0<code>url<\/code>\u00a0vari\u00e1vel \u00e9 apenas uma string de URL, como um endere\u00e7o da web.\u00a0Ele aponta para um local nos servidores Open Library.\u00a0Tamb\u00e9m inclui tr\u00eas\u00a0<em>par\u00e2metros<\/em>\u00a0(\u00a0<code>bibkeys<\/code>,\u00a0<code>jscmd<\/code>e\u00a0<code>format<\/code>) que informam aos servidores da Open Library quais informa\u00e7\u00f5es voc\u00ea est\u00e1 solicitando e como estruturar a resposta.\u00a0Nesse caso, voc\u00ea fornece o n\u00famero ISBN do livro para identific\u00e1-lo e pede que as informa\u00e7\u00f5es detalhadas sejam retornadas no formato JSON.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Nota:\u00a0Cada API p\u00fablica define seus pr\u00f3prios formatos para fazer solicita\u00e7\u00f5es e enviar resultados de volta.\u00a0Para que seu c\u00f3digo se comunique de maneira eficaz com uma API, voc\u00ea deve aderir aos formatos que ele define.\u00a0Para a Open Library, os formatos de solicita\u00e7\u00e3o e resposta s\u00e3o descritos na\u00a0<a href=\"https:\/\/openlibrary.org\/dev\/docs\/api\/books\" target=\"_blank\" rel=\"noopener noreferrer\">documenta\u00e7\u00e3o da API Open LIbrary Books<\/a>\u00a0.\u00a0O formato de resposta aqui \u00e9\u00a0<a href=\"https:\/\/www.json.org\/\" target=\"_blank\" rel=\"noopener noreferrer\"><em>JSON<\/em><\/a>\u00a0(JavaScript Object Notation), que \u00e9 apenas uma maneira particular de organizar dados;\u00a0JSON \u00e9 semelhante a HTML ou XML, mas tende a ser mais f\u00e1cil de ler para humanos.<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<p>Depois de criar a string do URL, o c\u00f3digo envia uma solicita\u00e7\u00e3o para esse local e recebe uma resposta.\u00a0Isso \u00e9 feito com o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/#urlfetchapp\" target=\"_blank\" rel=\"noopener noreferrer\"><code>UrlFetchApp.fetch(url, params)<\/code><\/a>\u00a0m\u00e9todo.\u00a0Este m\u00e9todo envia uma solicita\u00e7\u00e3o de informa\u00e7\u00e3o ao URL externo que voc\u00ea fornece e armazena a resposta resultante na\u00a0<code>response<\/code>\u00a0vari\u00e1vel.\u00a0Al\u00e9m do URL, o c\u00f3digo define o par\u00e2metro opcional\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/url-fetch-app#fetchurl-params\" target=\"_blank\" rel=\"noopener noreferrer\"><code>muteHttpExceptions<\/code><\/a>\u00a0como\u00a0<code>true<\/code>.\u00a0Essa configura\u00e7\u00e3o significa apenas que seu c\u00f3digo n\u00e3o parar\u00e1 se as solicita\u00e7\u00f5es resultarem em um erro de API;\u00a0em vez disso, a resposta de erro \u00e9 retornada.<\/p>\n<p>A solicita\u00e7\u00e3o retorna um\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/http-response\" target=\"_blank\" rel=\"noopener noreferrer\"><code>HTTPResponse<\/code><\/a>\u00a0objeto que est\u00e1 armazenado na\u00a0<code>response<\/code>\u00a0vari\u00e1vel.\u00a0As respostas HTTP incluem um c\u00f3digo de resposta, cabe\u00e7alhos HTTP e o conte\u00fado da resposta principal.\u00a0As informa\u00e7\u00f5es de interesse aqui s\u00e3o o conte\u00fado JSON principal, portanto, o c\u00f3digo deve extra\u00ed-lo e, em seguida, analisar o JSON para localizar e retornar as informa\u00e7\u00f5es desejadas.<\/p>\n<p>&nbsp;<\/p>\n<h5>2: Analise a resposta da API e retorne as informa\u00e7\u00f5es de interesse<\/h5>\n<p>Nas \u00faltimas tr\u00eas linhas do c\u00f3digo, o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/http-response#getContentText()\" target=\"_blank\" rel=\"noopener noreferrer\"><code>HTTPResponse.getContentText()<\/code><\/a>\u00a0m\u00e9todo retorna o conte\u00fado principal da resposta como uma string.\u00a0Esta string est\u00e1 no formato JSON, mas o conte\u00fado e formato exatos s\u00e3o definidos pela API Open Library.\u00a0O\u00a0<a href=\"https:\/\/www.w3schools.com\/js\/js_json_parse.asp\" target=\"_blank\" rel=\"noopener noreferrer\"><code>JSON.parse(jsonString)<\/code><\/a>\u00a0m\u00e9todo converte a string JSON em um objeto JavaScript para que diferentes partes dos dados possam ser facilmente extra\u00eddas.\u00a0Por fim, a fun\u00e7\u00e3o retorna a parte dos dados correspondente ao n\u00famero ISBN do livro de interesse.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Nota\u00a0: Se voc\u00ea sentir que precisa se familiarizar ainda mais com\u00a0<a href=\"https:\/\/www.json.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">JSON<\/a>\u00a0, consulte a documenta\u00e7\u00e3o\u00a0<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/JavaScript\/Objects\/JSON\" target=\"_blank\" rel=\"noopener noreferrer\">JavaScript para trabalhar com JSON<\/a>\u00a0ou a\u00a0<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/JSON\" target=\"_blank\" rel=\"noopener noreferrer\">refer\u00eancia de classe JSON JavaScript<\/a>\u00a0.<\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Agora que voc\u00ea implementou\u00a0<code>fetchBookData_(ISBN)<\/code>, outras fun\u00e7\u00f5es em seu c\u00f3digo podem rapidamente pesquisar informa\u00e7\u00f5es de qualquer livro usando seu n\u00famero ISBN.\u00a0Voc\u00ea usar\u00e1 esta fun\u00e7\u00e3o para ajudar a preencher os espa\u00e7os em branco em sua planilha.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h3 class=\"step-title\">Gravando dados da API em uma planilha<\/h3>\n<p>Agora voc\u00ea pode implementar uma nova\u00a0<code>fillInTheBlanks()<\/code>\u00a0fun\u00e7\u00e3o que far\u00e1 o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Identifique o t\u00edtulo ausente e os dados do autor dentro do intervalo de dados ativo.<\/li>\n<li>Recupere os dados ausentes de um livro espec\u00edfico chamando a API Open Library por meio do\u00a0<code>fetchBookData_(ISBN)<\/code>\u00a0m\u00e9todo auxiliar.<\/li>\n<li>Atualize o t\u00edtulo ausente e \/ ou os valores do autor em suas respectivas c\u00e9lulas.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Implementa\u00e7\u00e3o<\/h4>\n<p>Implemente essa nova fun\u00e7\u00e3o fazendo o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>No editor do Apps Script, adicione o seguinte c\u00f3digo ao final do seu projeto de script:<\/li>\n<\/ol>\n<pre><code><span class=\"com\">\/**\r\n * Fills in missing title and author data using Open Library API\r\n * calls.\r\n *\/<\/span> \r\n<span class=\"kwd\">function<\/span><span class=\"pln\"> fillInTheBlanks<\/span><span class=\"pun\">(){<\/span>\r\n  <span class=\"com\">\/\/ Constants that identify the index of the title, author,<\/span>\r\n  <span class=\"com\">\/\/ and ISBN columns (in the 2D bookValues array below). <\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> TITLE_COLUMN <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> AUTHOR_COLUMN <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">;<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> ISBN_COLUMN <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">2<\/span><span class=\"pun\">;<\/span>\r\n\r\n  <span class=\"com\">\/\/ Get the current book information in the active sheet. The data<\/span>\r\n  <span class=\"com\">\/\/ is placed into a 2D array.<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> dataRange <\/span><span class=\"pun\">=<\/span> <span class=\"typ\">SpreadsheetApp<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getActiveSpreadsheet<\/span><span class=\"pun\">()<\/span>\r\n    <span class=\"pun\">.<\/span><span class=\"pln\">getDataRange<\/span><span class=\"pun\">();<\/span>\r\n  <span class=\"kwd\">var<\/span><span class=\"pln\"> bookValues <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> dataRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">getValues<\/span><span class=\"pun\">();<\/span>\r\n\r\n  <span class=\"com\">\/\/ Examine each row of the data (excluding the header row).<\/span>\r\n  <span class=\"com\">\/\/ If an ISBN is present and a title or author is missing,<\/span>\r\n  <span class=\"com\">\/\/ use the fetchBookData_(isbn) method to retrieve the<\/span>\r\n  <span class=\"com\">\/\/ missing data from the Open Library API. Fill in the<\/span>\r\n  <span class=\"com\">\/\/ missing titles or authors when they are found.<\/span>\r\n  <span class=\"kwd\">for<\/span><span class=\"pun\">(<\/span><span class=\"kwd\">var<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> bookValues<\/span><span class=\"pun\">.<\/span><span class=\"pln\">length<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> row<\/span><span class=\"pun\">++){<\/span>   \r\n    <span class=\"kwd\">var<\/span><span class=\"pln\"> isbn <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"pln\">ISBN_COLUMN<\/span><span class=\"pun\">];<\/span>\r\n    <span class=\"kwd\">var<\/span><span class=\"pln\"> title <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"pln\">TITLE_COLUMN<\/span><span class=\"pun\">];<\/span>\r\n    <span class=\"kwd\">var<\/span><span class=\"pln\"> author <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> bookValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"pln\">AUTHOR_COLUMN<\/span><span class=\"pun\">];<\/span>\r\n   \r\n    <span class=\"kwd\">if<\/span><span class=\"pun\">(<\/span><span class=\"pln\">isbn <\/span><span class=\"pun\">!=<\/span> <span class=\"str\">\"\"<\/span> <span class=\"pun\">&amp;&amp;<\/span> <span class=\"pun\">(<\/span><span class=\"pln\">title <\/span><span class=\"pun\">===<\/span> <span class=\"str\">\"\"<\/span> <span class=\"pun\">||<\/span><span class=\"pln\"> author <\/span><span class=\"pun\">===<\/span> <span class=\"str\">\"\"<\/span><span class=\"pun\">)<\/span> <span class=\"pun\">){<\/span>\r\n      <span class=\"com\">\/\/ Only call the API if you have an ISBN number and<\/span>\r\n      <span class=\"com\">\/\/ either the title or author is missing.<\/span>\r\n      <span class=\"kwd\">var<\/span><span class=\"pln\"> bookData <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> fetchBookData_<\/span><span class=\"pun\">(<\/span><span class=\"pln\">isbn<\/span><span class=\"pun\">);<\/span>\r\n\r\n      <span class=\"com\">\/\/ Sometimes the API doesn't return the information needed.<\/span>\r\n      <span class=\"com\">\/\/ In those cases, don't attempt to update the row further.<\/span>\r\n      <span class=\"kwd\">if<\/span> <span class=\"pun\">(!<\/span><span class=\"pln\">bookData <\/span><span class=\"pun\">||<\/span> <span class=\"pun\">!<\/span><span class=\"pln\">bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">)<\/span> <span class=\"pun\">{<\/span>\r\n        <span class=\"kwd\">continue<\/span><span class=\"pun\">;<\/span>\r\n      <span class=\"pun\">}<\/span>\r\n\r\n      <span class=\"com\">\/\/ The API might not have a title, so only fill it in<\/span>\r\n      <span class=\"com\">\/\/ if the API returns one and the title is blank in the<\/span>\r\n      <span class=\"com\">\/\/ sheet.<\/span>\r\n      <span class=\"kwd\">if<\/span><span class=\"pun\">(<\/span><span class=\"pln\">title <\/span><span class=\"pun\">===<\/span> <span class=\"str\">\"\"<\/span> <span class=\"pun\">&amp;&amp;<\/span><span class=\"pln\"> bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">.<\/span><span class=\"pln\">title<\/span><span class=\"pun\">){<\/span><span class=\"pln\">\r\n        bookValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"pln\">TITLE_COLUMN<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\"> bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">.<\/span><span class=\"pln\">title<\/span><span class=\"pun\">;<\/span> \r\n      <span class=\"pun\">}<\/span>\r\n\r\n      <span class=\"com\">\/\/ The API might not have an author name, so only fill it in<\/span>\r\n      <span class=\"com\">\/\/ if the API returns one and the author is blank in the<\/span>\r\n      <span class=\"com\">\/\/ sheet.<\/span>\r\n      <span class=\"kwd\">if<\/span><span class=\"pun\">(<\/span><span class=\"pln\">author <\/span><span class=\"pun\">===<\/span> <span class=\"str\">\"\"<\/span> <span class=\"pun\">&amp;&amp;<\/span><span class=\"pln\"> bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">.<\/span><span class=\"pln\">authors\r\n          <\/span><span class=\"pun\">&amp;&amp;<\/span><span class=\"pln\"> bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">.<\/span><span class=\"pln\">authors<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">].<\/span><span class=\"pln\">name<\/span><span class=\"pun\">){<\/span><span class=\"pln\">\r\n        bookValues<\/span><span class=\"pun\">[<\/span><span class=\"pln\">row<\/span><span class=\"pun\">][<\/span><span class=\"pln\">AUTHOR_COLUMN<\/span><span class=\"pun\">]<\/span> <span class=\"pun\">=<\/span><span class=\"pln\">\r\n          bookData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">details<\/span><span class=\"pun\">.<\/span><span class=\"pln\">authors<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">].<\/span><span class=\"pln\">name<\/span><span class=\"pun\">;<\/span> \r\n      <span class=\"pun\">}<\/span>\r\n    <span class=\"pun\">}<\/span>\r\n  <span class=\"pun\">}<\/span>\r\n  \r\n  <span class=\"com\">\/\/ Put the updated book data values back into the spreadsheet.<\/span><span class=\"pln\">\r\n  dataRange<\/span><span class=\"pun\">.<\/span><span class=\"pln\">setValues<\/span><span class=\"pun\">(<\/span><span class=\"pln\">bookValues<\/span><span class=\"pun\">);<\/span>   \r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<ol start=\"2\" type=\"1\">\n<li>Salve seu projeto de script.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4>Revis\u00e3o de c\u00f3digo<\/h4>\n<p>Este c\u00f3digo \u00e9 dividido em tr\u00eas se\u00e7\u00f5es:<\/p>\n<p>&nbsp;<\/p>\n<h5>1: Lendo as informa\u00e7\u00f5es do livro existente<\/h5>\n<p>As primeiras tr\u00eas linhas da fun\u00e7\u00e3o definem algumas constantes que ajudam a tornar o c\u00f3digo mais leg\u00edvel.\u00a0Nas pr\u00f3ximas duas linhas, a\u00a0<code>bookValues<\/code>\u00a0vari\u00e1vel \u00e9 usada para manter uma c\u00f3pia local das informa\u00e7\u00f5es do livro da folha.\u00a0O c\u00f3digo ler\u00e1 as informa\u00e7\u00f5es\u00a0<code>bookValues<\/code>, usar\u00e1 a API para preencher as informa\u00e7\u00f5es ausentes e escrever\u00e1 esses valores de volta na planilha.<\/p>\n<p>&nbsp;<\/p>\n<aside class=\"special\">\u00a0 \u00a0 Observa\u00e7\u00e3o\u00a0: esse arranjo \u00e9 diferente do que voc\u00ea usou para\u00a0<code>splitAtFirstComma()<\/code>\u00a0e\u00a0<code>splitAtLastBy()<\/code>.\u00a0Nessas fun\u00e7\u00f5es, o c\u00f3digo examinava apenas os t\u00edtulos atualmente destacados e suas linhas.\u00a0Aqui, voc\u00ea est\u00e1 examinando a folha inteira usando\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/spreadsheet#getdatarange\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Spreadsheet.getDataRange()<\/code><\/a>.<\/p>\n<p>&nbsp;<\/p>\n<\/aside>\n<p>&nbsp;<\/p>\n<h5>2: Buscando informa\u00e7\u00f5es ausentes usando a fun\u00e7\u00e3o auxiliar<\/h5>\n<p>O c\u00f3digo ent\u00e3o percorre cada linha\u00a0<code>bookValues<\/code>\u00a0para procurar t\u00edtulos ou autores ausentes.\u00a0Para reduzir o n\u00famero de chamadas de API que o c\u00f3digo deve fazer (e assim evitar perda de tempo), o c\u00f3digo apenas chama a API se o seguinte for verdadeiro:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>A linha tem um valor na coluna ISBN (ou seja, o ISBN do livro \u00e9 conhecido).<\/li>\n<li>O t\u00edtulo ou a c\u00e9lula do autor nessa linha est\u00e3o vazios.<\/li>\n<\/ol>\n<p>Se todas as condi\u00e7\u00f5es forem verdadeiras, o c\u00f3digo chama a API usando a\u00a0<code>fetchBookData_(isbn)<\/code>\u00a0fun\u00e7\u00e3o auxiliar que voc\u00ea implementou e armazena o resultado na\u00a0<code>bookData<\/code>\u00a0vari\u00e1vel.\u00a0Esta vari\u00e1vel agora deve ter as informa\u00e7\u00f5es que faltam que voc\u00ea deseja escrever de volta na planilha.<\/p>\n<p>A \u00fanica tarefa que resta agora \u00e9 adicionar as\u00a0<code>bookData<\/code>\u00a0informa\u00e7\u00f5es \u00e0 nossa planilha.\u00a0No entanto, h\u00e1 uma ressalva.\u00a0Infelizmente, APIs p\u00fablicas como a API Open Library Book \u00e0s vezes n\u00e3o t\u00eam as informa\u00e7\u00f5es solicitadas ou, ocasionalmente, podem ter algum outro problema que o impede de fornecer essas informa\u00e7\u00f5es.\u00a0Se voc\u00ea assumir cegamente que todas as solicita\u00e7\u00f5es de API ser\u00e3o bem-sucedidas, seu c\u00f3digo n\u00e3o ser\u00e1 robusto o suficiente para lidar com erros inesperados.<\/p>\n<p>Para garantir que seu c\u00f3digo seja robusto em face de erros da API, o c\u00f3digo deve verificar se a resposta da API \u00e9 v\u00e1lida antes de tentar us\u00e1-la.\u00a0Uma vez que o c\u00f3digo tem\u00a0<code>bookData<\/code>, ele conduz um simples verifica sele\u00e7\u00e3o que\u00a0<code>bookData<\/code>\u00a0e\u00a0<code>bookData.details<\/code>\u00a0existem antes de tentar ler a partir deles.\u00a0Se algum estiver faltando, significa que a API n\u00e3o possui os dados que voc\u00ea deseja.\u00a0Nesse caso, o\u00a0<code>continue<\/code>\u00a0comando diz ao c\u00f3digo para pular essa linha &#8211; voc\u00ea n\u00e3o pode preencher as c\u00e9lulas ausentes, mas pelo menos seu script n\u00e3o travar\u00e1.<\/p>\n<p>&nbsp;<\/p>\n<h5>3: Escrever informa\u00e7\u00f5es atualizadas de volta na planilha<\/h5>\n<p>A pr\u00f3xima parte do c\u00f3digo tem verifica\u00e7\u00f5es semelhantes que verificam o t\u00edtulo retornado da API e as informa\u00e7\u00f5es do autor.\u00a0O c\u00f3digo s\u00f3 atualiza a\u00a0<code>bookValues<\/code>matriz se o t\u00edtulo original ou a c\u00e9lula do autor estiver vazia e a API retornar um valor que voc\u00ea pode colocar l\u00e1.<\/p>\n<p>O loop sai depois que todas as linhas da planilha s\u00e3o examinadas.\u00a0A \u00faltima etapa \u00e9 escrever o\u00a0<code>bookValues<\/code>array\u00a0agora atualizado de\u00a0volta na planilha usando\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluesvalues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValues(values)<\/code><\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h4>Resultados<\/h4>\n<p>Agora voc\u00ea pode terminar de limpar os dados do seu livro!\u00a0Fa\u00e7a o seguinte:<\/p>\n<ol start=\"1\" type=\"1\">\n<li>Se ainda n\u00e3o o fez, realce o intervalo A2: A15 em sua planilha e selecione\u00a0Lista de livros&gt; T\u00edtulo \/ autor separado na primeira v\u00edrgula\u00a0para limpar os problemas de v\u00edrgula.<\/li>\n<li>Se ainda n\u00e3o o fez, realce o intervalo A2: A15 em sua planilha e selecione\u00a0Lista de livros&gt; T\u00edtulo \/ autor separado por \u00faltimo &#8220;por&#8221;\u00a0para limpar os problemas &#8220;por&#8221;.<\/li>\n<li>Selecione Lista de\u00a0livros&gt; Preencher t\u00edtulos em branco e c\u00e9lulas de autor\u00a0para que seu c\u00f3digo preencha todas as c\u00e9lulas restantes:<\/li>\n<\/ol>\n<p class=\"image-container\"><img src=\"https:\/\/codelabs.developers.google.com\/codelabs\/apps-script-fundamentals-3\/img\/826675a3437adbdb.gif\" width=\"836\" height=\"300\" \/><\/p>\n<p class=\"image-container\">\n<h4 class=\"image-container\">O que voc\u00ea aprendeu?<\/h4>\n<ul>\n<li>Como importar dados de uma planilha do Google.<\/li>\n<li>Como criar um menu personalizado em\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\"><code>onOpen()<\/code><\/a>.<\/li>\n<li>Como analisar e manipular valores de dados de string.<\/li>\n<li>Como chamar APIs p\u00fablicas usando o\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">servi\u00e7o\u00a0<\/a><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">UrlFetch<\/a>\u00a0.<\/li>\n<li>Como analisar\u00a0dados do objeto\u00a0<a href=\"https:\/\/www.json.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">JSON<\/a>\u00a0recuperados de uma fonte de API p\u00fablica.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"image-container\">\n<aside class=\"special\">\n<h4>Conceitos-chave:<\/h4>\n<ol start=\"1\" type=\"1\">\n<li><code>onOpen()<\/code>\u00e9 um gatilho simples usado para criar itens de menu.\u00a0Os gatilhos simples t\u00eam uma variedade de\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#restrictions\" target=\"_blank\" rel=\"noopener noreferrer\">restri\u00e7\u00f5es que<\/a>\u00a0voc\u00ea deve seguir.<\/li>\n<li>Ao ler ou gravar dados de c\u00e9lula de planilha, \u00e9 uma pr\u00e1tica recomendada ler ou gravar um intervalo inteiro de uma vez com\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#getvalues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.getValues()<\/code><\/a>\u00a0ou\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range#setvaluesvalues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range.setValues(values)<\/code><\/a>.\u00a0N\u00e3o leia ou configure cada c\u00e9lula individualmente, pois isso ser\u00e1 muito mais lento.<\/li>\n<li>As fun\u00e7\u00f5es do Apps Script com nomes terminados em &#8220;_&#8221; s\u00e3o consideradas\u00a0<em>privadas<\/em>\u00a0.\u00a0Essas fun\u00e7\u00f5es n\u00e3o podem ser chamadas por outros scripts se inclu\u00eddas como parte de uma\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/libraries\" target=\"_blank\" rel=\"noopener noreferrer\">biblioteca<\/a>\u00a0ou por clientes por meio\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/html\/communication\" target=\"_blank\" rel=\"noopener noreferrer\">da comunica\u00e7\u00e3o cliente-servidor<\/a>\u00a0.\u00a0Se voc\u00ea sabe que uma fun\u00e7\u00e3o s\u00f3 ser\u00e1 usada pelo script em que est\u00e1, geralmente \u00e9 uma boa ideia terminar seu nome com &#8220;_&#8221;.<\/li>\n<li>Ao usar dados retornados por APIs externas, verifique se os dados retornados s\u00e3o v\u00e1lidos antes de tentar us\u00e1-los.\u00a0Isso diminuir\u00e1 a probabilidade de seu c\u00f3digo ter erros se a API retornar um resultado inesperado.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<\/aside>\n<aside class=\"special\">\n<h4>Termos-chave\u00a0:<\/h4>\n<ul>\n<li>Ativo (status)\u00a0: indica que a planilha, planilha, intervalo ou c\u00e9lula especificada \u00e9 a que est\u00e1 sendo exibida ou destacada pelo usu\u00e1rio da planilha.<\/li>\n<li>C\u00e9lula ativa\u00a0: a \u00fanica c\u00e9lula destacada na p\u00e1gina ativa que tem o foco do cursor<\/li>\n<li>Intervalo ativo\u00a0: o grupo de uma ou mais c\u00e9lulas atualmente destacadas na p\u00e1gina ativa.<\/li>\n<li>API\u00a0: interface de programa\u00e7\u00e3o de aplicativos;\u00a0este \u00e9 um servi\u00e7o que programas ou scripts podem contatar para recuperar informa\u00e7\u00f5es ou realizar a\u00e7\u00f5es espec\u00edficas.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/guides\/services\/authorization\" target=\"_blank\" rel=\"noopener noreferrer\">Autoriza\u00e7\u00e3o<\/a>\u00a0: o processo em que o usu\u00e1rio concede permiss\u00f5es para permitir que o Apps Script acesse dados privados nos servi\u00e7os relevantes do Google.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/guides\/bound\" target=\"_blank\" rel=\"noopener noreferrer\">Script vinculado ao cont\u00eainer<\/a>\u00a0: qualquer script vinculado e criado a partir de um documento do G Suite, como uma planilha ou um documento do Google.<\/li>\n<li>Fun\u00e7\u00e3o auxiliar\u00a0: uma fun\u00e7\u00e3o, geralmente privada, que \u00e9 chamada por outra pessoa para concluir uma pequena subtarefa.\u00a0As fun\u00e7\u00f5es auxiliares geralmente s\u00e3o usadas quando a subtarefa precisa ser realizada muitas vezes em locais diferentes.<\/li>\n<li><a href=\"https:\/\/www.json.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">JSON<\/a>\u00a0: formato de arquivo para definir objetos de dados e suas caracter\u00edsticas de texto.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#onopene\" target=\"_blank\" rel=\"noopener noreferrer\"><code>onOpen()<\/code><\/a>: Se definido em um script, um gatilho simples que dispara sempre que um arquivo \u00e9 aberto ou recarregado.<\/li>\n<li>Fun\u00e7\u00f5es privadas\u00a0: uma fun\u00e7\u00e3o que n\u00e3o pode ser chamada como parte de uma\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/libraries\" target=\"_blank\" rel=\"noopener noreferrer\">biblioteca<\/a>\u00a0ou por clientes atrav\u00e9s\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/html\/communication\" target=\"_blank\" rel=\"noopener noreferrer\">da comunica\u00e7\u00e3o cliente-servidor<\/a>\u00a0.\u00a0As fun\u00e7\u00f5es privadas do Apps Script t\u00eam nomes que terminam com &#8220;_&#8221;.<\/li>\n<li>Intervalo\u00a0: um intervalo representa um grupo de uma ou mais c\u00e9lulas adjacentes em uma p\u00e1gina.\u00a0A\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/range\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Range<\/code><\/a>\u00a0classe oferece a capacidade de ler e atualizar\u00a0intervalos\u00a0em uma planilha.<\/li>\n<li>Editor de script\u00a0: o editor de c\u00f3digo do Apps Script.<\/li>\n<li>Gatilhos simples\u00a0: um subtipo de\u00a0gatilhos\u00a0no Apps Script que t\u00eam nomes de fun\u00e7\u00e3o de gatilho reservados e certas\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/guides\/triggers\/#restrictions\" target=\"_blank\" rel=\"noopener noreferrer\">restri\u00e7\u00f5es<\/a>\u00a0;\u00a0por exemplo\u00a0<code>onOpen()<\/code>,.<\/li>\n<li>Folha\u00a0: uma \u00fanica p\u00e1gina de uma planilha.\u00a0A\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/sheet\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Sheet<\/code><\/a>\u00a0classe permite acessar e modificar planilhas.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/spreadsheet-app\" target=\"_blank\" rel=\"noopener noreferrer\"><code>SpreadsheetApp<\/code><\/a>: Esta classe serve como classe pai para o servi\u00e7o de planilha e fornece um ponto de partida para o c\u00f3digo que l\u00ea ou manipula dados do Planilhas Google.<\/li>\n<li>Planilha\u00a0: um arquivo do Planilhas Google que reside no Google Drive.\u00a0A\u00a0<a href=\"https:\/\/developers.google.com\/apps-script\/reference\/spreadsheet\/spreadsheet\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Spreadsheet<\/code><\/a>\u00a0classe permite que voc\u00ea acesse e modifique planilhas.<\/li>\n<li>Gatilhos\u00a0: um evento vinculado a uma fun\u00e7\u00e3o do Apps Script.\u00a0Quando o evento (como uma planilha sendo aberta) ocorre, o acionador &#8220;dispara&#8221; e executa automaticamente a fun\u00e7\u00e3o do Apps Script associada.<\/li>\n<li><a href=\"https:\/\/developers.google.com\/apps-script\/reference\/url-fetch\/\" target=\"_blank\" rel=\"noopener noreferrer\">UrlFetch<\/a>\u00a0: o servi\u00e7o Apps Script que permite que os scripts se conectem a endpoints de URL para fazer solicita\u00e7\u00f5es e receber respostas.<\/li>\n<\/ul>\n<\/aside>\n","protected":false},"excerpt":{"rendered":"<p>Configurando Os exerc\u00edcios neste codelab requerem uma planilha para funcionar. Siga estas etapas para criar uma nova planilha para usar nestes exerc\u00edcios: Crie uma nova planilha em seu Google Drive.\u00a0Voc\u00ea pode fazer isso na\u00a0interface\u00a0do\u00a0Drive\u00a0selecionando\u00a0Novo&gt; Planilhas Google\u00a0.\u00a0A nova planilha \u00e9 colocada em seu Drive raiz por padr\u00e3o. Clique no t\u00edtulo da planilha e altere de &#8220;Planilha [&hellip;]<\/p>\n","protected":false},"author":667,"featured_media":0,"parent":349,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"jetpack_post_was_ever_published":false,"footnotes":""},"class_list":["post-707","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/pages\/707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/users\/667"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/comments?post=707"}],"version-history":[{"count":4,"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/pages\/707\/revisions"}],"predecessor-version":[{"id":733,"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/pages\/707\/revisions\/733"}],"up":[{"embeddable":true,"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/pages\/349"}],"wp:attachment":[{"href":"https:\/\/wp.ufpel.edu.br\/planilhasgoogle\/wp-json\/wp\/v2\/media?parent=707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}