اصول اسکریپت برنامه ها با برگه های Google شماره 3: کار با داده ها

1. مقدمه

به بخش سوم از فهرست پخش کدهای صفحه کدهای Google Sheets با اسکریپت اصولی برنامه ها خوش آمدید.

با تکمیل این لبه کد، می‌توانید نحوه استفاده از دستکاری داده‌ها، منوهای سفارشی و بازیابی عمومی API داده‌ها در Apps Script را برای بهبود تجربه کاربرگ‌های خود بیاموزید. شما به کار با کلاس‌های SpreadsheetApp ، Spreadsheet ، Sheet و Range ادامه خواهید داد که کدهای قبلی در این لیست پخش معرفی شده‌اند.

چیزی که یاد خواهید گرفت

  • نحوه وارد کردن داده ها از صفحه گسترده شخصی یا مشترک در Drive.
  • نحوه ایجاد یک منوی سفارشی با تابع onOpen() .
  • نحوه تجزیه و دستکاری مقادیر داده رشته در سلول‌های Google Sheet.
  • نحوه استخراج و دستکاری داده های شی JSON از یک منبع API عمومی.

قبل از اینکه شروع کنی

این سومین لبه کد در فهرست پخش Fundamentals of Apps Script with Google Sheets است. قبل از شروع این کد لبه، حتماً کدهای قبلی را تکمیل کنید:

  1. ماکروها و توابع سفارشی
  2. صفحات گسترده، برگه ها و محدوده ها

آنچه شما نیاز دارید

  • درک موضوعات اساسی Apps Script که در کدهای قبلی این لیست پخش کاوش شده است.
  • آشنایی اولیه با ویرایشگر Apps Script
  • آشنایی اولیه با Google Sheets
  • قابلیت خواندن Sheets A1 Notation
  • آشنایی اولیه با جاوا اسکریپت و کلاس String آن

2. راه اندازی کنید

تمرین‌های این نرم‌افزار برای کار کردن به یک صفحه‌گسترده نیاز دارند. این مراحل را برای ایجاد صفحه‌گسترده برای استفاده در این تمرین‌ها دنبال کنید:

  1. یک صفحه گسترده در Google Drive خود ایجاد کنید. می‌توانید این کار را از رابط Drive با انتخاب New > Google Sheets انجام دهید. این صفحه گسترده جدید شما را ایجاد و باز می کند. فایل در پوشه Drive شما ذخیره می شود.
  2. روی عنوان صفحه‌گسترده کلیک کنید و آن را از «صفحه گسترده بدون عنوان» به «دستکاری داده‌ها و منوهای سفارشی» تغییر دهید. برگه شما باید به شکل زیر باشد:

545c02912de7d112.png

  1. برای باز کردن ویرایشگر اسکریپت، روی Extensions > Apps Script کلیک کنید
  2. روی عنوان پروژه Apps Script کلیک کنید و آن را از "پروژه بدون عنوان" به "Data Manipulation and Custom Menus" تغییر دهید. روی تغییر نام کلیک کنید تا تغییر عنوان ذخیره شود.

با یک صفحه گسترده و پروژه خالی، آماده شروع آزمایشگاه هستید. برای شروع یادگیری در مورد منوهای سفارشی، به بخش بعدی بروید.

3. نمای کلی: داده ها را با یک آیتم منوی سفارشی وارد کنید

Apps Script به شما امکان تعریف منوهای سفارشی را می دهد که می توانند در Google Sheets ظاهر شوند. همچنین می‌توانید از منوهای سفارشی در Google Docs، Google Slides و Google Forms استفاده کنید. هنگامی که یک آیتم منوی سفارشی را تعریف می کنید، یک برچسب متنی ایجاد می کنید و آن را به یک تابع Apps Script در پروژه اسکریپت خود متصل می کنید. سپس می توانید منو را به UI اضافه کنید تا در Google Sheets ظاهر شود:

d6b694da6b8c6783.png

وقتی کاربر روی یک آیتم منوی سفارشی کلیک می‌کند، تابع Apps Script که با آن مرتبط کرده‌اید اجرا می‌شود. این یک روش سریع برای اجرای عملکردهای Apps Script بدون نیاز به باز کردن ویرایشگر اسکریپت است. همچنین به دیگر کاربران صفحه‌گسترده اجازه می‌دهد تا کد شما را بدون نیاز به دانستن چیزی در مورد نحوه عملکرد یا نحوه عملکرد Apps Script اجرا کنند. برای آنها، این فقط یکی دیگر از آیتم های منو است.

آیتم های منوی سفارشی در تابع ماشه ساده onOpen() تعریف شده اند که در بخش بعدی با آن آشنا خواهید شد.

4. تابع ()onOpen

راه‌اندازهای ساده در Apps Script راهی برای اجرای کد Apps Script خاص در پاسخ به شرایط یا رویدادهای خاص ارائه می‌دهند. هنگامی که یک ماشه ایجاد می کنید، مشخص می کنید که چه رویدادی باعث فعال شدن تریگر می شود و یک تابع Apps Script را ارائه می دهید که برای رویداد اجرا می شود.

onOpen() نمونه ای از یک تریگر ساده است. راه‌اندازی آن‌ها آسان است—تنها کاری که باید انجام دهید این است که یک تابع Apps Script به نام onOpen() بنویسید و هر بار که صفحه گسترده مرتبط باز یا بارگذاری مجدد می‌شود، Apps Script آن را اجرا می‌کند:

/**
 * A special function that runs when the spreadsheet is first
 * opened or reloaded. onOpen() is used to add custom menu
 * items to the spreadsheet.
 */
function onOpen() {
 /* ... */ 
}

پیاده سازی

بیایید یک منوی سفارشی ایجاد کنیم.

  1. کد زیر را در پروژه اسکریپت خود جایگزین کنید:
/**
 * A special function that runs when the spreadsheet is first
 * opened or reloaded. onOpen() is used to add custom menu
 * items to the spreadsheet.
 */
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Book-list')
    .addItem('Load Book-list', 'loadBookList')
    .addToUi();
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

بیایید این کد را بررسی کنیم تا بفهمیم چگونه کار می کند. در onOpen() خط اول از getUi() برای بدست آوردن یک شی Ui استفاده می کند که نمایانگر رابط کاربری صفحه گسترده فعالی است که این اسکریپت به آن محدود شده است.

سه خط بعدی منو ( Book-list ) را ایجاد می کنند، یک آیتم منو ( Load Book-list ) را به آن منو اضافه می کنند و سپس منو را به رابط صفحه گسترده اضافه می کنند. این کار به ترتیب با createMenu(caption) ، addItem(caption, functionName) و addToUi() انجام می شود.

روش addItem(caption, functionName) یک ارتباط بین برچسب آیتم منو و تابع Apps Script ایجاد می کند که با انتخاب آیتم منو اجرا می شود. در این حالت، انتخاب آیتم منوی Load Book-list باعث می‌شود که Sheets تلاش کند تا تابع loadBookList() را اجرا کند (که هنوز وجود ندارد).

نتایج

اکنون این تابع را اجرا کنید تا ببینید کار می کند:

  1. در Google Sheets، صفحه‌گسترده‌تان را دوباره بارگیری کنید. توجه: این معمولاً برگه را با ویرایشگر اسکریپت شما می بندد.
  2. با انتخاب ابزار > ویرایشگر اسکریپت، ویرایشگر اسکریپت خود را دوباره باز کنید.

پس از بارگیری مجدد صفحه گسترده، منوی Book-list جدید باید در نوار منو ظاهر شود:

687dfb214f2930ba.png

با کلیک کردن روی Book-list ، می توانید منوی حاصل را مشاهده کنید:

8a4a391fbabcb16a.png

بخش بعدی کد تابع loadBookList() را ایجاد می‌کند و یکی از راه‌های تعامل با داده‌ها در Apps Script را معرفی می‌کند: خواندن صفحات گسترده دیگر.

5. داده های صفحه گسترده را وارد کنید

اکنون که یک منوی سفارشی ایجاد کرده‌اید، می‌توانید توابعی ایجاد کنید که با کلیک کردن روی آیتم منو قابل اجرا باشند.

در حال حاضر، منوی سفارشی Book-list یک آیتم منو دارد: Load Book-list. تابعی که هنگام انتخاب آیتم منوی Load Book-list ، loadBookList(), می شود، در اسکریپت شما وجود ندارد، بنابراین انتخاب Book-list > Load Book-list یک خطا ایجاد می کند:

b94dcef066e7041d.gif

می توانید این خطا را با اجرای تابع loadBookList() برطرف کنید.

پیاده سازی

شما می‌خواهید که آیتم منوی جدید صفحه‌گسترده را با داده‌هایی پر کند تا با آن کار کنید، بنابراین loadBookList() را برای خواندن داده‌های کتاب از صفحه‌گسترده دیگر و کپی کردن آن در صفحه‌گسترده دیگر پیاده‌سازی می‌کنید:

  1. کد زیر را در زیر onOpen() به اسکریپت خود اضافه کنید:
/** 
 * Creates a template book list based on the
 * provided 'codelab-book-list' sheet.
 */
function loadBookList(){
  // Gets the active sheet.
  var sheet = SpreadsheetApp.getActiveSheet();
  
  // Gets a different spreadsheet from Drive using
  // the spreadsheet's ID. 
  var bookSS = SpreadsheetApp.openById(
    "1c0GvbVUDeBmhTpq_A3vJh2xsebtLuwGwpBYqcOBqGvo" 
  );

  // Gets the sheet, data range, and values of the
  // spreadsheet stored in bookSS.
  var bookSheet = bookSS.getSheetByName("codelab-book-list");
  var bookRange = bookSheet.getDataRange();
  var bookListValues = bookRange.getValues();

  // Add those values to the active sheet in the current
  // spreadsheet. This overwrites any values already there.
  sheet.getRange(1, 1, bookRange.getHeight(), bookRange.getWidth()) 
    .setValues(bookListValues);
  
  // Rename the destination sheet and resize the data
  // columns for easier reading.
  sheet.setName("Book-list");
  sheet.autoResizeColumns(1, 3);
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

بنابراین این تابع چگونه کار می کند؟ تابع loadBookList() از متدهایی عمدتاً از کلاس‌های Spreadsheet ، Sheet و Range استفاده می‌کند که آزمایشگاه‌های کد قبلی معرفی شدند. با در نظر گرفتن این مفاهیم، ​​می توانید کد loadBookList() را به چهار بخش زیر تقسیم کنید:

1: برگه مقصد را مشخص کنید

خط اول از SpreadsheetApp.getActiveSheet() برای دریافت ارجاع به شی برگه فعلی و ذخیره آن در sheet متغیر استفاده می کند. این برگه ای است که داده ها در آن کپی می شوند.

2: داده های منبع را شناسایی کنید

چند خط بعدی چهار متغیر را ایجاد می کند که به داده های منبعی که شما بازیابی می کنید اشاره دارد:

  • bookSS یک مرجع به صفحه گسترده ای که کد از آن داده ها را می خواند ذخیره می کند. کد صفحه‌گسترده را با شناسه صفحه‌گسترده‌اش پیدا می‌کند. در این مثال، شناسه صفحه‌گسترده منبع را برای خواندن از آن ارائه کردیم و صفحه‌گسترده را با استفاده از روش SpreadsheetApp.openById(id) باز کردیم.
  • bookSheet ارجاع به صفحه ای را در bookSS می کند که حاوی داده های مورد نظر شما است. کد برگه ای را که باید از آن خوانده شود با نام آن، codelab-book-list مشخص می کند.
  • bookRange یک مرجع به طیف وسیعی از داده ها را در bookSheet می کند. متد Sheet.getDataRange() محدوده ای را برمی گرداند که شامل تمام سلول های غیر خالی در برگه است. این یک راه آسان برای اطمینان از دریافت محدوده ای است که تمام داده های یک برگه را بدون درج ردیف و ستون خالی پوشش می دهد.
  • bookListValues ​​یک آرایه دو بعدی است که حاوی تمام مقادیر گرفته شده از سلول های bookRange است. Range.getValues() این آرایه را با خواندن داده ها از صفحه منبع تولید می کند.

3: داده ها را از مبدا تا مقصد کپی کنید

بخش کد بعدی داده های bookListValues ​​را در sheet کپی می کند و سپس نام آن را نیز تغییر می دهد:

  • Sheet.getRange(row, column, numRows, numColumns) برای شناسایی محل کپی کردن داده ها در sheet استفاده می شود.
  • Range.getHeight() و Range.getWidth() برای اندازه گیری اندازه داده ها و تعریف محدوده مقصد با ابعاد مشابه استفاده می شوند.
  • Range.setValues(values) آرایه دوبعدی bookListValues ​​را در محدوده مقصد کپی می کند و هر داده ای را که از قبل وجود دارد، رونویسی می کند.

4: برگه مقصد را فرمت کنید

Sheet.setName(name) برای تغییر نام برگه مقصد به Book-list استفاده می شود. آخرین خط در تابع از Sheet.autoResizeColumns(startColumn, numColumns) برای تغییر اندازه سه ستون اول در برگه مقصد استفاده می کند و به شما امکان می دهد داده های جدید را راحت تر بخوانید.

نتایج

می توانید این عملکرد را در عمل مشاهده کنید. در Google Sheets، Book-list > Load book-list را انتخاب کنید تا عملکرد پر کردن صفحه گسترده خود را اجرا کنید:

3c797e1e2b9fe641.gif

اکنون برگه‌ای با فهرستی از عناوین کتاب، نویسندگان و شماره‌های 13 رقمی ISBN دارید. در بخش بعدی، نحوه اصلاح و به روز رسانی داده های این فهرست کتاب را با استفاده از دستکاری رشته و منوهای سفارشی خواهید آموخت.

6. نمای کلی: داده های صفحه گسترده را پاک کنید

شما اکنون اطلاعات کتاب را در برگه خود دارید. هر ردیف به کتاب خاصی اشاره دارد و عنوان، نویسنده و شماره شابک آن را در ستون‌های جداگانه ذکر می‌کند. با این حال، می توانید برخی از مشکلات را با این داده های خام مشاهده کنید:

  1. برای برخی از ردیف‌ها، عنوان و نویسنده در ستون عنوان با هم قرار می‌گیرند و با کاما یا رشته «با» به هم مرتبط می‌شوند.
  2. برخی از ردیف‌ها عنوان یا نویسنده کتاب را ندارند.

در بخش‌های بعدی، با پاک کردن داده‌ها، این مشکلات را اصلاح خواهید کرد. برای شماره اول، توابعی ایجاد می‌کنید که ستون عنوان را می‌خوانند و هر زمان که یک کاما یا جداکننده «با» یافت می‌شود، متن را تقسیم می‌کند و زیررشته‌های نویسنده و عنوان مربوطه را در ستون‌های درست قرار می‌دهد. برای شماره دوم، کدی می نویسید که به طور خودکار اطلاعات کتاب گم شده را با استفاده از یک API خارجی جستجو می کند و آن اطلاعات را به برگه شما اضافه می کند.

7. موارد منو را اضافه کنید

شما می‌خواهید سه آیتم منو برای کنترل عملیات پاک‌سازی داده‌ها ایجاد کنید.

پیاده سازی

اجازه دهید onOpen() را به‌روزرسانی کنیم تا آیتم‌های منوی اضافی را که به آن نیاز دارید، در بر گیرد. موارد زیر را انجام دهید:

  1. در پروژه اسکریپت خود، کد onOpen() خود را برای مطابقت با موارد زیر به روز کنید:
/**
 * A special function that runs when the spreadsheet is first
 * opened or reloaded. onOpen() is used to add custom menu
 * items to the spreadsheet.
 */
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Book-list')
    .addItem('Load Book-list', 'loadBookList')
    .addSeparator()
    .addItem(
      'Separate title/author at first comma', 'splitAtFirstComma')
    .addItem(
      'Separate title/author at last "by"', 'splitAtLastBy')
    .addSeparator()
    .addItem(
      'Fill in blank titles and author cells', 'fillInTheBlanks')
    .addToUi();
}
  1. پروژه اسکریپت خود را ذخیره کنید
  2. در ویرایشگر اسکریپت، onOpen را از لیست توابع انتخاب کنید و روی Run کلیک کنید. این روی onOpen() اجرا می‌شود تا منوی صفحه‌گسترده را دوباره بسازد تا نیازی به بارگیری مجدد صفحه‌گسترده نباشد.

در این کد جدید، Menu.addSeparator() یک تقسیم‌کننده افقی در منو ایجاد می‌کند تا گروه‌هایی از آیتم‌های منو مرتبط را به‌صورت بصری سازماندهی کنند. آیتم‌های منوی جدید در زیر آن اضافه می‌شوند، با برچسب‌های Separate title/author at first comma ، Separate title/author at last "by" و Fill in blank titles and author cells .

نتایج

در صفحه گسترده خود، روی منوی Book-list کلیک کنید تا موارد منوی جدید را مشاهده کنید:

580c806ce8fd4872.png

کلیک کردن روی این موارد جدید باعث ایجاد خطا می شود زیرا عملکردهای مربوطه آنها را پیاده سازی نکرده اید، بنابراین اجازه دهید این کار را در مرحله بعد انجام دهیم.

8. متن را بر روی جداکننده های کاما تقسیم کنید

مجموعه داده‌ای که به صفحه‌گسترده خود وارد کرده‌اید دارای چند سلول است که نویسنده و عنوان به اشتباه در یک سلول با استفاده از کاما ترکیب شده‌اند:

ca91c43c4e51d6b5.png

تقسیم رشته‌های متنی به ستون‌های جداگانه یک کار معمول صفحه‌گسترده است. Google Sheets یک تابع SPLIT() ارائه می دهد که رشته ها را به ستون ها تقسیم می کند. با این حال، مجموعه داده‌ها اغلب مشکلاتی دارند که نمی‌توان آنها را به راحتی با توابع داخلی Sheets حل کرد. در این موارد، می‌توانید کد Apps Script را بنویسید تا عملیات پیچیده مورد نیاز برای تمیز کردن و سازمان‌دهی داده‌های خود را انجام دهید.

ابتدا با اجرای تابعی به نام splitAtFirstComma() که نویسنده و عنوان را به سلول های مربوطه خود در هنگام یافتن ویرگول تقسیم می کند، پاکسازی داده های خود را شروع کنید.

تابع splitAtFirstComma() باید مراحل زیر را انجام دهد:

  1. محدوده نشان دهنده سلول های انتخاب شده فعلی را دریافت کنید.
  2. بررسی کنید که آیا سلول‌های محدوده دارای کاما هستند یا خیر.
  3. در جایی که کاما یافت می شود، رشته را به دو (و فقط دو) زیر رشته در محل کاما اول تقسیم کنید. برای ساده‌تر کردن کارها، می‌توانید فرض کنید که هر کاما نشان‌دهنده یک الگوی رشته‌ای « [نویسندگان]، [عنوان] » است. شما همچنین می توانید فرض کنید که اگر چندین کاما در سلول ظاهر می شود، مناسب است که روی اولین کاما در رشته تقسیم شود.
  4. رشته های فرعی را به عنوان محتوای جدید سلول های عنوان و نویسنده مربوطه تنظیم کنید.

پیاده سازی

برای اجرای این مراحل، از همان روش‌های سرویس صفحه گسترده استفاده می‌کنید که قبلاً استفاده می‌کردید، اما همچنین باید از جاوا اسکریپت برای دستکاری داده‌های رشته استفاده کنید. مراحل زیر را انجام دهید:

  1. در ویرایشگر Apps Script، تابع زیر را به انتهای پروژه اسکریپت خود اضافه کنید:
/**
 * Reformats title and author columns by splitting the title column
 * at the first comma, if present.
 */
function splitAtFirstComma(){
  // Get the active (currently highlighted) range.
  var activeRange = SpreadsheetApp.getActiveRange();
  var titleAuthorRange = activeRange.offset(
    0, 0, activeRange.getHeight(), activeRange.getWidth() + 1);

  // Get the current values of the selected title column cells.
  // This is a 2D array.
  var titleAuthorValues = titleAuthorRange.getValues();

  // Update values where commas are found. Assumes the presence
  // of a comma indicates an "authors, title" pattern.
  for (var row = 0; row < titleAuthorValues.length; row++){
    var indexOfFirstComma =
        titleAuthorValues[row][0].indexOf(", ");

    if(indexOfFirstComma >= 0){
      // Found a comma, so split and update the values in
      // the values array.
      var titlesAndAuthors = titleAuthorValues[row][0];

      // Update the title value in the array.
      titleAuthorValues[row][0] =
        titlesAndAuthors.slice(indexOfFirstComma + 2);

      // Update the author value in the array.
      titleAuthorValues[row][1] =
        titlesAndAuthors.slice(0, indexOfFirstComma);
    }
  }

  // Put the updated values back into the spreadsheet.
  titleAuthorRange.setValues(titleAuthorValues);
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

بیایید کد جدید را بررسی کنیم که از سه بخش اصلی تشکیل شده است:

1: مقادیر عنوان برجسته شده را بازیابی کنید

سه خط اول سه متغیر را ایجاد می کند که به داده های فعلی در برگه اشاره دارد:

  • activeRange محدوده ای را نشان می دهد که کاربر در حال حاضر هنگام فراخوانی تابع splitAtFirstComma() آن را برجسته کرده است. برای ساده نگه داشتن این تمرین، می‌توانیم فرض کنیم که کاربر تنها زمانی این کار را انجام می‌دهد که سلول‌های ستون A را برجسته می‌کند.
  • titleAuthorRange محدوده جدیدی را نشان می‌دهد که سلول‌های مشابه activeRange را پوشش می‌دهد، اما همچنین شامل یک ستون دیگر در سمت راست است. titleAuthorRange با استفاده از روش Range.offset(rowOffset, columnOffset, numRows, numColumns) می شود. کد به این محدوده گسترده نیاز دارد زیرا به مکانی برای قرار دادن هر نویسنده ای که پیدا می کند در ستون عنوان نیاز دارد.
  • titleAuthorValues ​​یک آرایه دو بعدی از داده ها است که از titleAuthorRange با استفاده از Range.getValues() استخراج شده است.

2: هر عنوان را بررسی کنید و بر روی اولین جداکننده کاما که پیدا شد تقسیم کنید

بخش بعدی مقادیر titleAuthorValues ​​را برای یافتن کاما بررسی می کند. یک JavaScript For Loop برای بررسی تمام مقادیر در ستون اول titleAuthorValues ​​استفاده می شود. هنگامی که یک زیر رشته کاما ( ", " ) با استفاده از متد indexOf() جاوا اسکریپت String یافت می شود، کد زیر را انجام می دهد:

  1. مقدار رشته سلول در متغیر titlesAndAuthors کپی می شود.
  2. مکان کاما با استفاده از روش indexOf() جاوا اسکریپت تعیین می شود.
  3. متد slice() String جاوا اسکریپت دوبار فراخوانی می شود تا رشته فرعی قبل از جداکننده کاما و زیر رشته بعد از جداکننده به دست آید.
  4. رشته های فرعی دوباره در آرایه titleAuthorValues ​​2D کپی می شوند و مقادیر موجود در آن موقعیت را بازنویسی می کنند. از آنجایی که ما یک الگوی " [نویسندگان]، [عنوان] " را فرض می کنیم، ترتیب دو رشته فرعی برعکس می شود تا عنوان در ستون اول و نویسندگان در ستون دوم قرار گیرد.

توجه: زمانی که کد یک کاما پیدا نمی کند، داده های ردیف را بدون تغییر می گذارد.

3: مقادیر جدید را دوباره در برگه کپی کنید

پس از بررسی تمام مقادیر سلول عنوان، آرایه به روز شده titleAuthorValues ​​2D با استفاده از روش Range.setValues(values) در صفحه گسترده کپی می شود.

نتایج

اکنون می توانید اثرات تابع splitAtFirstComma() را در عمل مشاهده کنید. سعی کنید آن را با انتخاب گزینه جدا کردن عنوان/نویسنده در منوی کاما پس از انتخاب... اجرا کنید.

... یک سلول:

a24763b60b305376.gif

... یا چندین سلول:

89c5c89b357d3713.gif

اکنون یک تابع Apps Script ساخته‌اید که داده‌های Sheets را پردازش می‌کند. در مرحله بعد، تابع تقسیم کننده دوم را پیاده سازی خواهید کرد.

9. متن را بر روی جداکننده های «توسط» تقسیم کنید

با نگاه کردن به داده های اصلی، می توانید مشکل دیگری را مشاهده کنید. همانطور که برخی از داده ها عناوین و نویسندگان را در یک سلول به صورت "[نویسندگان]، [عنوان]" قالب بندی می کنند، سلول های دیگر نویسنده و عنوان را به عنوان "[عنوان] توسط [نویسندگان]" قالب بندی می کنند:

41f0dd5ac63b62f4.png

پیاده سازی

شما می توانید این مشکل را با استفاده از تکنیک مشابه در قسمت آخر حل کنید و تابعی به نام splitAtLastBy() ایجاد کنید. این تابع کار مشابهی با splitAtFirstComma() —تنها تفاوت واقعی آن جستجوی یک الگوی متن متفاوت است. این تابع را با انجام موارد زیر پیاده سازی کنید:

  1. در ویرایشگر Apps Script، تابع زیر را به انتهای پروژه اسکریپت خود اضافه کنید:
/** 
 * Reformats title and author columns by splitting the title column
 * at the last instance of the string " by ", if present.
 */
function splitAtLastBy(){
  // Get the active (currently highlighted) range.
  var activeRange = SpreadsheetApp.getActiveRange();
  var titleAuthorRange = activeRange.offset(
    0, 0, activeRange.getHeight(), activeRange.getWidth() + 1);

  // Get the current values of the selected title column cells.
  // This is a 2D array.
  var titleAuthorValues = titleAuthorRange.getValues();

  // Update values where " by " substrings are found. Assumes
  // the presence of a " by " indicates a "title by authors"
  // pattern.
  for(var row = 0; row < titleAuthorValues.length; row++){
    var indexOfLastBy =
        titleAuthorValues[row][0].lastIndexOf(" by ");
    
    if(indexOfLastBy >= 0){
      // Found a " by ", so split and update the values in
      // the values array.
      var titlesAndAuthors = titleAuthorValues[row][0];
      
      // Update the title value in the array.
      titleAuthorValues[row][0] =
        titlesAndAuthors.slice(0, indexOfLastBy);
      
      // Update the author value in the array.
      titleAuthorValues[row][1] =
        titlesAndAuthors.slice(indexOfLastBy + 4);
    }
  }

  // Put the updated values back into the spreadsheet.
  titleAuthorRange.setValues(titleAuthorValues);
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

چند تفاوت کلیدی بین این کد و splitAtFirstComma() وجود دارد:

  1. رشته فرعی " by " به جای " , " به عنوان جداکننده رشته استفاده می شود.
  2. در اینجا از متد JavaScript String.lastIndexOf(substring) به جای String.indexOf(substring) استفاده می شود. این بدان معناست که اگر چندین زیررشته " by " در رشته اولیه وجود داشته باشد، همه آنها به جز آخرین " by " بخشی از عنوان فرض می شوند.
  3. پس از تقسیم رشته، رشته فرعی اول به عنوان عنوان و دومی به عنوان نویسنده تنظیم می شود (این ترتیب مخالف splitAtFirstComma() است).

نتایج

اکنون می توانید اثرات تابع splitAtLastBy() را در عمل مشاهده کنید. سعی کنید آن را با انتخاب گزینه جدا کردن عنوان/نویسنده در نهایت "توسط" منو پس از انتخاب... اجرا کنید.

... یک سلول:

4e6679e134145975.gif

... یا چندین سلول:

3c879c572c61e62f.gif

شما این بخش از Codelab را تکمیل کرده اید. اکنون می‌توانید از Apps Script برای خواندن و اصلاح داده‌های رشته در یک برگه استفاده کنید و از منوهای سفارشی برای اجرای دستورات Apps Script مختلف استفاده کنید.

در بخش بعدی، نحوه بهبود بیشتر این مجموعه داده را با پر کردن سلول‌های خالی با داده‌های گرفته‌شده از یک API عمومی خواهید آموخت.

10. نمای کلی: داده ها را از API های عمومی دریافت کنید

تاکنون مجموعه داده‌های خود را برای رفع برخی مشکلات قالب‌بندی عنوان و نویسنده اصلاح کرده‌اید، اما مجموعه داده هنوز برخی از اطلاعات را ندارد که در سلول‌های زیر مشخص شده است:

af0dba8cb09d1a49.png

با استفاده از عملیات رشته ای روی داده هایی که در حال حاضر دارید، نمی توانید داده های از دست رفته را دریافت کنید. در عوض، باید داده های گم شده را از منبع دیگری دریافت کنید. می‌توانید این کار را در Apps Script با درخواست اطلاعات از APIهای خارجی که می‌توانند داده‌های اضافی ارائه کنند، انجام دهید.

API ها رابط های برنامه نویسی کاربردی هستند. این یک اصطلاح کلی است، اما اساساً سرویسی است که برنامه‌ها و اسکریپت‌های شما می‌توانند برای درخواست اطلاعات یا انجام اقدامات خاصی تماس بگیرند. در این بخش، شما با یک API در دسترس عموم تماس می‌گیرید تا اطلاعات کتابی را که می‌توانید در سلول‌های خالی برگه خود درج کنید، درخواست کنید.

این بخش به شما می آموزد که چگونه:

  • اطلاعات کتاب را از یک منبع API خارجی درخواست کنید.
  • اطلاعات عنوان و نویسنده را از داده های برگشتی استخراج کنید و در صفحه گسترده خود بنویسید.

11. داده های خارجی را با UrlFetch واکشی کنید

قبل از بررسی کدهایی که مستقیماً با صفحه‌گسترده شما کار می‌کند، می‌توانید با ایجاد یک تابع کمکی مخصوصاً برای درخواست اطلاعات کتاب از API عمومی Open Library ، درباره کار با APIهای خارجی در Apps Script اطلاعات کسب کنید.

تابع کمکی ما، fetchBookData_(ISBN) ، یک عدد ISBN 13 رقمی از یک کتاب را به عنوان پارامتر می گیرد و داده های مربوط به آن کتاب را برمی گرداند. به Open Library API متصل می شود و اطلاعات را از آن بازیابی می کند و سپس شی JSON برگشتی را تجزیه می کند .

پیاده سازی

این تابع کمکی را با انجام موارد زیر پیاده سازی کنید:

  1. در ویرایشگر Apps Script، کد زیر را به انتهای اسکریپت خود اضافه کنید:
/**
 * Helper function to retrieve book data from the Open Library
 * public API.
 *
 * @param {number} ISBN - The ISBN number of the book to find.
 * @return {object} The book's data, in JSON format.
 */
function fetchBookData_(ISBN){
  // Connect to the public API.
  var url = "https://openlibrary.org/api/books?bibkeys=ISBN:"
      + ISBN + "&jscmd=details&format=json";
  var response = UrlFetchApp.fetch(
      url, {'muteHttpExceptions': true});
  
  // Make request to API and get response before this point.
  var json = response.getContentText();
  var bookData = JSON.parse(json); 
  
  // Return only the data we're interested in.
  return bookData['ISBN:' + ISBN];
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

این کد به دو بخش اصلی تقسیم می شود:

1: درخواست API

در دو خط اول، fetchBookData_(ISBN) با استفاده از نقطه پایانی URL API و Apps Script's URL Fetch Service به API عمومی Open Library متصل می شود.

متغیر url فقط یک رشته URL است، مانند یک آدرس وب. به مکانی در سرورهای Open Library اشاره می کند. همچنین شامل سه پارامتر ( bibkeys ، jscmd و format ) است که به سرورهای Open Library می‌گوید چه اطلاعاتی را درخواست می‌کنید و چگونه پاسخ را ساختار دهند. در این صورت، شماره شابک کتاب را ارائه می‌کنید و درخواست می‌کنید که اطلاعات دقیق با فرمت JSON برگردانده شود.

هنگامی که رشته URL را ساختید، کد درخواستی را به مکان ارسال می کند و پاسخ دریافت می کند. این کار با روش UrlFetchApp.fetch(url, params) انجام می شود. این درخواست اطلاعات را به URL خارجی که شما ارائه می کنید ارسال می کند و پاسخ حاصل را در متغیر response ذخیره می کند. علاوه بر URL، کد پارامتر اختیاری muteHttpExceptions را روی true تنظیم می کند. این تنظیم به این معنی است که اگر درخواست منجر به خطای API شود، کد شما متوقف نخواهد شد. در عوض، پاسخ خطا برگردانده می شود.

درخواست یک شی HTTPResponse را که در متغیر response ذخیره شده است برمی گرداند. پاسخ‌های HTTP شامل کد پاسخ، سرصفحه‌های HTTP و محتوای پاسخ اصلی است. اطلاعات مورد علاقه در اینجا محتوای اصلی JSON است، بنابراین کد باید آن را استخراج کند و سپس JSON را تجزیه کند تا اطلاعات مورد نظر را پیدا کرده و برگرداند.

2: پاسخ API را تجزیه کنید و اطلاعات مورد نظر را برگردانید

در سه خط آخر کد، متد HTTPResponse.getContentText() محتوای اصلی پاسخ را به صورت رشته برمی گرداند. این رشته در قالب JSON است، اما Open Library API محتوا و قالب دقیق را تعریف می کند. متد JSON.parse(jsonString) رشته JSON را به یک شی جاوا اسکریپت تبدیل می کند تا بخش های مختلف داده به راحتی استخراج شوند. در نهایت، تابع داده های مربوط به شماره ISBN کتاب را برمی گرداند.

نتایج

اکنون که fetchBookData_(ISBN) را پیاده‌سازی کرده‌اید، سایر توابع در کد شما می‌توانند اطلاعات هر کتابی را با استفاده از شماره ISBN آن پیدا کنند. شما از این تابع برای کمک به پر کردن سلول های صفحه گسترده خود استفاده خواهید کرد.

12. داده های API را در صفحه گسترده بنویسید

اکنون می توانید تابع fillInTheBlanks() را پیاده سازی کنید که کارهای زیر را انجام می دهد:

  1. داده های عنوان و نویسنده از دست رفته را در محدوده داده فعال شناسایی کنید.
  2. با فراخوانی Open Library API با استفاده از روش کمکی fetchBookData_(ISBN) ، داده های از دست رفته یک کتاب خاص را بازیابی کنید.
  3. مقادیر عنوان یا نویسنده از دست رفته را در سلول های مربوطه به روز کنید.

پیاده سازی

این تابع جدید را با انجام موارد زیر پیاده سازی کنید:

  1. در ویرایشگر Apps Script، کد زیر را به انتهای پروژه اسکریپت خود اضافه کنید:
/**
 * Fills in missing title and author data using Open Library API
 * calls.
 */ 
function fillInTheBlanks(){
  // Constants that identify the index of the title, author,
  // and ISBN columns (in the 2D bookValues array below). 
  var TITLE_COLUMN = 0;
  var AUTHOR_COLUMN = 1;
  var ISBN_COLUMN = 2;

  // Get the existing book information in the active sheet. The data
  // is placed into a 2D array.
  var dataRange = SpreadsheetApp.getActiveSpreadsheet()
    .getDataRange();
  var bookValues = dataRange.getValues();

  // Examine each row of the data (excluding the header row).
  // If an ISBN is present, and a title or author is missing,
  // use the fetchBookData_(isbn) method to retrieve the
  // missing data from the Open Library API. Fill in the
  // missing titles or authors when they're found.
  for(var row = 1; row < bookValues.length; row++){   
    var isbn = bookValues[row][ISBN_COLUMN];
    var title = bookValues[row][TITLE_COLUMN];
    var author = bookValues[row][AUTHOR_COLUMN];
   
    if(isbn != "" && (title === "" || author === "") ){
      // Only call the API if you have an ISBN number and
      // either the title or author is missing.
      var bookData = fetchBookData_(isbn);

      // Sometimes the API doesn't return the information needed.
      // In those cases, don't attempt to update the row.
      if (!bookData || !bookData.details) {
        continue;
      }

      // The API might not return a title, so only fill it in
      // if the response has one and if the title is blank in
      // the sheet.
      if(title === "" && bookData.details.title){
        bookValues[row][TITLE_COLUMN] = bookData.details.title; 
      }

      // The API might not return an author name, so only fill it in
      // if the response has one and if the author is blank in
      // the sheet.
      if(author === "" && bookData.details.authors
          && bookData.details.authors[0].name){
        bookValues[row][AUTHOR_COLUMN] =
          bookData.details.authors[0].name; 
      }
    }
  }
  
  // Insert the updated book data values into the spreadsheet.
  dataRange.setValues(bookValues);
}
  1. پروژه اسکریپت خود را ذخیره کنید

بررسی کد

این کد به سه بخش تقسیم می شود:

1: اطلاعات کتاب موجود را بخوانید

سه خط اول تابع، ثابت هایی را برای کمک به خوانایی بیشتر کد تعریف می کند. در دو خط بعدی، از متغیر bookValues ​​برای نگهداری یک کپی محلی از اطلاعات کتاب برگه استفاده می شود. کد اطلاعات را از bookValues ​​می خواند، از API برای پر کردن اطلاعات از دست رفته استفاده می کند و این مقادیر را به صفحه گسترده باز می نویسد.

2: اطلاعات گمشده را با استفاده از تابع helper واکشی کنید

این کد روی هر ردیف در bookValues ​​حلقه می زند تا عناوین یا نویسندگان گمشده را پیدا کند. برای کاهش تعداد تماس‌های API و در عین حال بهبود کارایی، کد فقط در صورتی API را فراخوانی می‌کند که موارد زیر درست باشد:

  1. ستون ISBN ردیف دارای یک مقدار است.
  2. سلول عنوان یا نویسنده در ردیف خالی است.

اگر شرایط درست باشد، کد با استفاده از تابع کمکی fetchBookData_(isbn) که قبلاً پیاده‌سازی کرده‌اید، API را فراخوانی می‌کند و نتیجه را در متغیر bookData . اکنون باید اطلاعات گمشده ای را داشته باشد که می خواهید در برگه درج کنید.

تنها کار باقی مانده اضافه کردن اطلاعات bookData به صفحه گسترده است. با این حال، یک هشدار وجود دارد. متأسفانه، APIهای عمومی مانند Open Library Book API گاهی اطلاعاتی را که شما درخواست می کنید ندارند، یا گاهی ممکن است مشکل دیگری وجود داشته باشد که مانع از ارائه اطلاعات توسط آن شود. اگر فرض کنید هر درخواست API موفقیت آمیز خواهد بود، کد شما به اندازه کافی قوی نخواهد بود تا بتواند خطاهای غیرمنتظره را مدیریت کند.

برای اطمینان از اینکه کد شما می تواند خطاهای API را مدیریت کند، کد باید قبل از استفاده از آن، معتبر بودن پاسخ API را بررسی کند. هنگامی که کد دارای bookData ، یک بررسی ساده برای تأیید وجود bookData و bookData.details قبل از تلاش برای خواندن از آنها انجام می دهد. اگر یکی از آنها وجود نداشته باشد، به این معنی است که API داده های مورد نظر شما را ندارد. در این مورد، دستور continue به کد می‌گوید که از آن ردیف بگذرد—شما نمی‌توانید سلول‌های از دست رفته را پر کنید، اما حداقل اسکریپت شما خراب نمی‌شود.

3: اطلاعات به روز شده را دوباره در برگه بنویسید

آخرین قسمت کد دارای بررسی های مشابهی برای تأیید اطلاعات عنوان و نویسنده API است. کد فقط در صورتی آرایه bookValues ​​را به روز می کند که عنوان اصلی یا سلول نویسنده خالی باشد و API مقداری را که می توانید در آنجا قرار دهید برگرداند.

حلقه پس از بررسی تمام ردیف های برگه خارج می شود. آخرین مرحله این است که با استفاده از Range.setValues(values) آرایه bookValues ​​که اکنون به روز شده است را به صفحه گسترده بازنویسی کنید.

نتایج

اکنون می توانید پاک کردن داده های کتاب خود را به پایان برسانید. موارد زیر را انجام دهید:

  1. اگر هنوز این کار را نکرده‌اید، محدوده A2:A15 را در برگه خود برجسته کنید و فهرست Book-Separate title/author در ابتدا کاما را انتخاب کنید تا مشکلات کاما پاک شود.
  2. اگر هنوز این کار را نکرده‌اید، محدوده A2:A15 را در برگه خود برجسته کنید و فهرست Book-Separate title/author را در نهایت «by» انتخاب کنید تا مشکلات «by» پاک شود.
  3. برای پر کردن تمام سلول‌های باقی‌مانده، فهرست کتاب > پر کردن عناوین خالی و سلول‌های نویسنده را انتخاب کنید:

826675a3437adbdb.gif

13. نتیجه گیری

بابت تکمیل این کد لبه تبریک می گویم. شما یاد گرفته اید که چگونه منوهای سفارشی ایجاد کنید تا قسمت های مختلف کد Apps Script خود را فعال کنید. همچنین نحوه وارد کردن داده‌ها را با استفاده از سرویس‌های Apps Script و APIهای عمومی به Google Sheets مشاهده کرده‌اید. این یک عملیات رایج در پردازش صفحه گسترده است و Apps Script به شما امکان می دهد داده ها را از طیف گسترده ای از منابع وارد کنید. در نهایت، دیدید که چگونه می توانید از خدمات Apps Script و JavaScript برای خواندن، پردازش و درج داده های صفحه گسترده استفاده کنید.

آیا این کد لبه را مفید یافتید؟

آره خیر

چیزی که یاد گرفتی

  • نحوه وارد کردن داده ها از صفحه گسترده گوگل
  • نحوه ایجاد یک منوی سفارشی در تابع onOpen() .
  • نحوه تجزیه و دستکاری مقادیر داده های رشته ای
  • نحوه فراخوانی APIهای عمومی با استفاده از سرویس واکشی URL
  • چگونه داده های شی JSON بازیابی شده از یک منبع API عمومی را تجزیه کنیم.

What's next

The next codelab in this playlist goes into more depth on how to format data within a spreadsheet.

Find the next codelab at Data formatting .