محاسبه مسافت رانندگی & متر را به مایل تبدیل کنید

سطح کدنویسی : مبتدی
مدت زمان : ۱۰ دقیقه
نوع پروژه : عملکرد سفارشی و اتوماسیون با منوی سفارشی

اهداف

  • بفهمید که راه حل چه کاری انجام می‌دهد.
  • درک کنید که سرویس‌های Apps Script در این راهکار چه کاری انجام می‌دهند.
  • اسکریپت را تنظیم کنید.
  • اسکریپت را اجرا کنید.

درباره این راهکار

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

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

چگونه کار می‌کند؟

این اسکریپت از ۲ تابع سفارشی و یک اتوماسیون استفاده می‌کند.

  • تابع drivingDistance(origin, destination) از سرویس Maps برای محاسبه‌ی مسیرهای رانندگی بین دو مکان استفاده می‌کند و فاصله‌ی بین دو آدرس را بر حسب متر برمی‌گرداند.
  • تابع metersToMiles(meters) معادل تعداد مایل برای تعداد مشخصی متر را محاسبه می‌کند.
  • این اتوماسیون از کاربر می‌خواهد که ردیف آدرس‌های شروع و پایان را برای محاسبه مسیرهای رانندگی وارد کند و مسیرهای رانندگی گام به گام را به یک برگه جدید اضافه می‌کند.

سرویس‌های اسکریپت برنامه‌ها

این راهکار از سرویس‌های زیر استفاده می‌کند:

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

پیش‌نیازها

برای استفاده از این نمونه، به پیش‌نیازهای زیر نیاز دارید:

  • یک حساب گوگل (حساب‌های کاربری گوگل ورک‌اسپیس ممکن است نیاز به تأیید مدیر داشته باشند).
  • یک مرورگر وب با دسترسی به اینترنت.

اسکریپت را تنظیم کنید

  1. یک کپی از صفحه گسترده محاسبه مسافت رانندگی و تبدیل متر به مایل تهیه کنید. پروژه Apps Script برای این راه حل به صفحه گسترده پیوست شده است.
    یک کپی تهیه کنید
  2. برای افزودن سرصفحه‌ها و داده‌های نمایشی به برگه خود، روی مسیرها > آماده‌سازی برگه کلیک کنید. ممکن است لازم باشد صفحه را برای نمایش این منوی سفارشی، رفرش کنید.
  3. وقتی از شما خواسته شد، اسکریپت را تأیید کنید. اگر صفحه رضایت OAuth هشدار « این برنامه تأیید نشده است» را نشان می‌دهد، با انتخاب Advanced > Go to {Project Name} (unsafe) ادامه دهید.

  4. دوباره روی مسیرها > آماده‌سازی برگه کلیک کنید.

اسکریپت را اجرا کنید

  1. در سلول C2 ، فرمول =DRIVINGDISTANCE(A2,B2) وارد کنید و Enter را بزنید. اگر در مکانی هستید که از کامای اعشاری استفاده می‌کند، ممکن است لازم باشد به جای آن =DRIVINGDISTANCE(A2;B2) وارد کنید.
  2. در سلول D2 ، فرمول =METERSTOMILES(C2) را وارد کنید و Enter را بزنید.
  3. (اختیاری) ردیف‌های اضافی از آدرس‌های شروع و پایان اضافه کنید و فرمول‌های ستون‌های C و D را کپی کنید تا مسافت رانندگی بین مکان‌های مختلف محاسبه شود.
  4. روی مسیرها > تولید گام به گام کلیک کنید.
  5. در کادر محاوره‌ای، شماره ردیف آدرس‌هایی را که می‌خواهید برای آنها مسیر ایجاد کنید، وارد کنید و روی تأیید کلیک کنید.
  6. مسیرهای رانندگی را در برگه جدیدی که اسکریپت ایجاد می‌کند، مرور کنید.

کد را بررسی کنید

برای بررسی کد Apps Script برای این راهکار، روی مشاهده کد منبع در زیر کلیک کنید:

مشاهده کد منبع

کد.gs

sheets/customFunctions/customFunctions.gs
/**
 * @OnlyCurrentDoc Limits the script to only accessing the current sheet.
 */

/**
 * A special function that runs when the spreadsheet is open, used to add a
 * custom menu to the spreadsheet.
 */
function onOpen() {
  try {
    const spreadsheet = SpreadsheetApp.getActive();
    const menuItems = [
      {name: 'Prepare sheet...', functionName: 'prepareSheet_'},
      {name: 'Generate step-by-step...', functionName: 'generateStepByStep_'}
    ];
    spreadsheet.addMenu('Directions', menuItems);
  } catch (e) {
    // TODO (Developer) - Handle Exception
    console.log('Failed with error: %s' + e.error);
  }
}

/**
 * A custom function that converts meters to miles.
 *
 * @param {Number} meters The distance in meters.
 * @return {Number} The distance in miles.
 */
function metersToMiles(meters) {
  if (typeof meters !== 'number') {
    return null;
  }
  return meters / 1000 * 0.621371;
}

/**
 * A custom function that gets the driving distance between two addresses.
 *
 * @param {String} origin The starting address.
 * @param {String} destination The ending address.
 * @return {Number} The distance in meters.
 */
function drivingDistance(origin, destination) {
  const directions = getDirections_(origin, destination);
  return directions.routes[0].legs[0].distance.value;
}

/**
 * A function that adds headers and some initial data to the spreadsheet.
 */
function prepareSheet_() {
  try {
    const sheet = SpreadsheetApp.getActiveSheet().setName('Settings');
    const headers = [
      'Start Address',
      'End Address',
      'Driving Distance (meters)',
      'Driving Distance (miles)'];
    const initialData = [
      '350 5th Ave, New York, NY 10118',
      '405 Lexington Ave, New York, NY 10174'];
    sheet.getRange('A1:D1').setValues([headers]).setFontWeight('bold');
    sheet.getRange('A2:B2').setValues([initialData]);
    sheet.setFrozenRows(1);
    sheet.autoResizeColumns(1, 4);
  } catch (e) {
    // TODO (Developer) - Handle Exception
    console.log('Failed with error: %s' + e.error);
  }
}

/**
 * Creates a new sheet containing step-by-step directions between the two
 * addresses on the "Settings" sheet that the user selected.
 */
function generateStepByStep_() {
  try {
    const spreadsheet = SpreadsheetApp.getActive();
    const settingsSheet = spreadsheet.getSheetByName('Settings');
    settingsSheet.activate();

    // Prompt the user for a row number.
    const selectedRow = Browser
        .inputBox('Generate step-by-step', 'Please enter the row number of' +
        ' the' + ' addresses to use' + ' (for example, "2"):',
        Browser.Buttons.OK_CANCEL);
    if (selectedRow === 'cancel') {
      return;
    }
    const rowNumber = Number(selectedRow);
    if (isNaN(rowNumber) || rowNumber < 2 ||
      rowNumber > settingsSheet.getLastRow()) {
      Browser.msgBox('Error',
          Utilities.formatString('Row "%s" is not valid.', selectedRow),
          Browser.Buttons.OK);
      return;
    }


    // Retrieve the addresses in that row.
    const row = settingsSheet.getRange(rowNumber, 1, 1, 2);
    const rowValues = row.getValues();
    const origin = rowValues[0][0];
    const destination = rowValues[0][1];
    if (!origin || !destination) {
      Browser.msgBox('Error', 'Row does not contain two addresses.',
          Browser.Buttons.OK);
      return;
    }

    // Get the raw directions information.
    const directions = getDirections_(origin, destination);

    // Create a new sheet and append the steps in the directions.
    const sheetName = 'Driving Directions for Row ' + rowNumber;
    let directionsSheet = spreadsheet.getSheetByName(sheetName);
    if (directionsSheet) {
      directionsSheet.clear();
      directionsSheet.activate();
    } else {
      directionsSheet =
        spreadsheet.insertSheet(sheetName, spreadsheet.getNumSheets());
    }
    const sheetTitle = Utilities
        .formatString('Driving Directions from %s to %s', origin, destination);
    const headers = [
      [sheetTitle, '', ''],
      ['Step', 'Distance (Meters)', 'Distance (Miles)']
    ];
    const newRows = [];
    for (const step of directions.routes[0].legs[0].steps) {
      // Remove HTML tags from the instructions.
      const instructions = step.html_instructions
          .replace(/<br>|<div.*?>/g, '\n').replace(/<.*?>/g, '');
      newRows.push([
        instructions,
        step.distance.value
      ]);
    }
    directionsSheet.getRange(1, 1, headers.length, 3).setValues(headers);
    directionsSheet.getRange(headers.length + 1, 1, newRows.length, 2)
        .setValues(newRows);
    directionsSheet.getRange(headers.length + 1, 3, newRows.length, 1)
        .setFormulaR1C1('=METERSTOMILES(R[0]C[-1])');

    // Format the new sheet.
    directionsSheet.getRange('A1:C1').merge().setBackground('#ddddee');
    directionsSheet.getRange('A1:2').setFontWeight('bold');
    directionsSheet.setColumnWidth(1, 500);
    directionsSheet.getRange('B2:C').setVerticalAlignment('top');
    directionsSheet.getRange('C2:C').setNumberFormat('0.00');
    const stepsRange = directionsSheet.getDataRange()
        .offset(2, 0, directionsSheet.getLastRow() - 2);
    setAlternatingRowBackgroundColors_(stepsRange, '#ffffff', '#eeeeee');
    directionsSheet.setFrozenRows(2);
    SpreadsheetApp.flush();
  } catch (e) {
    // TODO (Developer) - Handle Exception
    console.log('Failed with error: %s' + e.error);
  }
}

/**
 * Sets the background colors for alternating rows within the range.
 * @param {Range} range The range to change the background colors of.
 * @param {string} oddColor The color to apply to odd rows (relative to the
 *     start of the range).
 * @param {string} evenColor The color to apply to even rows (relative to the
 *     start of the range).
 */
function setAlternatingRowBackgroundColors_(range, oddColor, evenColor) {
  const backgrounds = [];
  for (let row = 1; row <= range.getNumRows(); row++) {
    const rowBackgrounds = [];
    for (let column = 1; column <= range.getNumColumns(); column++) {
      if (row % 2 === 0) {
        rowBackgrounds.push(evenColor);
      } else {
        rowBackgrounds.push(oddColor);
      }
    }
    backgrounds.push(rowBackgrounds);
  }
  range.setBackgrounds(backgrounds);
}

/**
 * A shared helper function used to obtain the full set of directions
 * information between two addresses. Uses the Apps Script Maps Service.
 *
 * @param {String} origin The starting address.
 * @param {String} destination The ending address.
 * @return {Object} The directions response object.
 */
function getDirections_(origin, destination) {
  const directionFinder = Maps.newDirectionFinder();
  directionFinder.setOrigin(origin);
  directionFinder.setDestination(destination);
  const directions = directionFinder.getDirections();
  if (directions.status !== 'OK') {
    throw directions.error_message;
  }
  return directions;
}

مشارکت‌کنندگان

این نمونه توسط گوگل و با کمک متخصصان توسعه‌دهنده گوگل نگهداری می‌شود.

مراحل بعدی