광밤
광밤
Moderator
🏅 AI 마스터
🎖️ 마스터 파트너
🚀 SNS 챌린지 달성자

[Apps Script] 구글 시트(Sales Pipeline) 업데이트 ➡️ 이메일 알림 발송 ✚ 캘린더 등록

*본 게시물은 지피터스 AI게시글 서포터 GPT를 활용하여 작성하였습니다.
(텍스트는 수정 없이 위 GPT가 제공해준 원문을 그대로 사용했고, 링크 및 이미지 삽입만 추가 했습니다.)

소개

- 구글 시트의 데이터 업데이트를 자동화하여 이메일 알림 전송 및 구글 캘린더 이벤트 생성을 목표로 했습니다.

- 처음에는 제미나이(Gemini)를 통해 자동화를 시도했으나, 해당 요구사항을 지원하지 않아 Google Workspace 환경에 적합한 앱스크립트를 추천받아 활용하게 되었습니다.


진행 방법

  • 사용 도구: 구글 앱스크립트(Apps Script)

  • 사용한 스크립트의 주요 기능:

    • K열 (Next Activity Date)가 수정되면 구글 캘린더에 새로운 이벤트를 생성합니다.

    • E열 (Stage)가 수정되면 지정된 이메일로 알림을 전송합니다.

  • 주요 프롬프트

아래 구글 시트를 다음 조건을 만족하도록 apps script 코드를 작성해줘. 
(코드뿐 아니라 환경 설정에 대해서도 최대한 단계적으로 쉽게 설명) 

1. Deals 시트의 'Next Activity Date'가 업데이트되면 내 Google Calendar 에 해당 일자로 등록해주고, 캘린더 discription 엔 해당 Contact 및 Notes 의 내용을 작성해줘. 캘린더 알림은 기본적으로 1시간전으로 설정해줘.
2. Deals 시트의 'Stage'가 업데이트되면, 내가 지정한 이메일 주소로 메일을 발송해줘. 각 단계를 이메일 제목으로 하고, 해당 단계에 따른 격려 메시지와 핵심이 되는 액션아이템 제시를 본문으로 해줘 

*apps script 코드 작성을 위해 추가적으로 더 필요한 정보가 있으면 내게 요청해~

---
구글 시트 링크:
https://docs.google.com/spreadsheets/d/1sIXr7dz8GfUaCCfht2V3D8iATozlfzYwq_vjA_4G2hE/edit?usp=sharing

+ 구글 시트 링크를 읽어 오지는 못하여, Deals 시트의 구조를 최대한 자세히 설명했습니다.

(지금부터는... 무려 2시간의 시행착오를 통해🥲😫 인내를 배우고 앱스크립트 기본기까지 마스터하게 되는 과정!)

검정색 배경에 한국어 텍스트
검정색 배경에 한국어 텍스트
한국어 텍스트가 있는 검은 화면

마침내...🫥🫨😇 전체 진행 프로세스와 함께 최종 구글 앱스크립트의 코드를 보여 드릴 수 있게 되었습니다!!


전체 프로세스

  • Google Sheet 설정

    • 대상 Sheet 이름: DEALS

    • 주요 열:

      • K열 (Next Activity Date): 수정 시 캘린더 이벤트 생성.

      • E열 (Stage): 수정 시 이메일 전송.

      • B열 (Contact): 이벤트나 이메일에 사용될 Contact 정보.

      • L열 (Notes): 이벤트 설명에 사용될 추가 정보.

  • Apps Script 설정

    • Google Sheets 상단 메뉴에서 확장 프로그램 > Apps Script를 클릭.

    • 열리는 Apps Script 창에서 아래 코드를 복사하여 붙여넣기.

function onEdit(e) {

  try {

    if (!e || !e.range) {

      Logger.log("No edit event object found. Make sure the event is triggered from Google Sheets.");

      return;

    }

    const sheet = e.source.getActiveSheet();

    const range = e.range;

    const row = range.getRow();

    const col = range.getColumn();

    Logger.log(`Edit detected in sheet: ${sheet.getName()}, Row: ${row}, Column: ${col}`);

    if (sheet.getName() !== "DEALS") {

      Logger.log(`This edit is not in the 'DEALS' sheet. Current sheet: ${sheet.getName()}`);

      return;

    }

    const nextActivityDateCol = 11; // K열 (Next Activity Date)

    const stageCol = 5; // E열 (Stage)

    // K열 (Next Activity Date) 수정 시

    if (col === nextActivityDateCol && row >= 12) {

      const nextActivityDate = sheet.getRange(row, nextActivityDateCol).getValue();

      const contact = sheet.getRange(row, 2).getValue(); // B열 (Contact)

      const notes = sheet.getRange(row, 12).getValue(); // L열 (Notes)

      if (nextActivityDate) {

        Logger.log(`Adding calendar event: Contact=${contact}, Date=${nextActivityDate}, Notes=${notes}`);

        addEventToCalendar(nextActivityDate, contact, notes);

      } else {

        Logger.log("No Next Activity Date provided. Skipping calendar update.");

      }

    }

    // E열 (Stage) 수정 시

    if (col === stageCol && row >= 12) {

      const stage = sheet.getRange(row, stageCol).getValue();

      const contact = sheet.getRange(row, 2).getValue(); // B열 (Contact)

      const company = sheet.getRange(row, 1).getValue(); // A열 (Company)

      Logger.log(`Stage updated to: ${stage}`);

      sendEmailNotification(stage, contact, company);

    }

  } catch (error) {

    Logger.log(`Error in onEdit: ${error.message}`);

  }

}

// Google Calendar에 이벤트 추가 (오전 9시 고정)

function addEventToCalendar(date, contact, notes) {

  try {

    const calendar = CalendarApp.getDefaultCalendar(); // 기본 캘린더 사용

    const startTime = new Date(date);

    startTime.setHours(9, 0, 0, 0); // 오전 9시 고정

    const endTime = new Date(startTime.getTime() + 3600000); // 1시간 후 종료

    const event = calendar.createEvent(

      Follow-up with ${contact},

      startTime,

      endTime,

      {

        description: Contact: ${contact}\nNotes: ${notes},

        reminders: [{ method: 'popup', minutes: 60 }]

      }

    );

    Logger.log(`Calendar event created: ${event.getTitle()} on ${event.getStartTime()}`);

  } catch (error) {

    Logger.log(`Error in addEventToCalendar: ${error.message}`);

  }

}

// 이메일 전송

function sendEmailNotification(stage, contact, company) {

  try {

    const email = "[email protected]"; // 이메일 주소

    const subject = Stage Update: ${stage} - ${contact} - ${company};

    let message = "";

    // 단계별 액션아이템 문구 작성

    switch (stage) {

      case "Lead":

        message = "리드 단계: 영업팀에 연락하여 첫 미팅을 준비하세요.";

        break;

      case "Opportunity":

        message = "기회 단계: 고객과의 관계를 강화하고 니즈를 파악하세요.";

        break;

      case "Demo":

        message = "데모 단계: 데모 준비를 위해 개발팀에 의뢰하세요.";

        break;

      case "Quote":

        message = "견적 단계: 재무팀에 고객이 거절할 수 없는 견적서 작성을 요청하세요.";

        break;

      case "Closed Won":

        message = "축하합니다! 계약이 체결되었습니다. 다음 단계를 진행하세요.";

        break;

      case "Closed Lost":

        message = "계약이 종료되었습니다. 이유를 분석하고 향후 전략을 수정하세요.";

        break;

      default:

        message = "단계가 업데이트되었습니다. 다음 단계를 준비하세요.";

        break;

    }

    GmailApp.sendEmail(email, subject, message);

    Logger.log(`Email sent to ${email} with subject: "${subject}"`);

  } catch (error) {

    Logger.log(`Error in sendEmailNotification: ${error.message}`);

  }

}
  • 트리거 설정

    • Apps Script 편집기에서 왼쪽 시계 모양 아이콘 (Triggers) 클릭.

    • + Add Trigger 버튼 클릭.

    • 설정:

      • Function to run: onEdit

      • Event source: From spreadsheet

      • Event type: On edit

    • 저장 후 트리거가 설정되었는지 확인.

  • 권한 승인 요청

    • 스크립트를 처음 실행하면 Google 권한 승인이 필요합니다.

    • 표시되는 승인 화면에서 고급 > 안전하지 않은 페이지로 이동을 클릭한 후 승인하세요.

  • 테스트 방법

    • Google Sheets로 이동하여 DEALS 시트를 엽니다.

    • K열 (Next Activity Date):

      • 날짜를 수정하거나 추가합니다.

      • Google Calendar에서 이벤트가 생성되었는지 확인합니다.

    • E열 (Stage):

      • 단계를 변경합니다.

      • [email protected] 이메일로 알림이 수신되었는지 확인합니다.

    • Apps Script 편집기에서 Execution Logs를 확인하여 스크립트 실행 결과를 점검합니다.

  • 결과가 나오지 않을 경우

    • 트리거 문제: 트리거 설정이 올바른지 다시 확인합니다.

    • Execution Logs: 실행 로그를 확인하여 오류 메시지를 기반으로 문제를 해결합니다.


결과와 배운 점

  • 배운 점: 구글 앱스크립트를 통해 Google Workspace 환경에서 데이터 변경을 자동으로 처리하는 간단한 방법을 체득했습니다. + 이젠 n8n도 잘 할 수 있을 것 같은 자신감 한스푼🥄

  • 실패담: 처음에 제미나이를 선택했지만, 해당 요구사항을 해결하지 못해 앱스크립트로 변경했습니다.

  • 계획: 앞으로 다른 Google Workspace 도구와도 모두 다 연동하여 자동화 워크플로를 확장할 예정입니다.


도움 받은 글

5

👉 이 게시글도 읽어보세요