커뮤니티
포인트
쿠폰
내 강의실
국비 신청 내역
증명서
계정
로그아웃
학습 질문
개발 일지
나의 활동
답변 완료
5주차 5-8를 다시 듣는 중인데
[왕초보] 칼퇴를 부르는 파이썬 업무 자동화
5주차
북마크
은*현
댓글
1
추천
0
조회수
8
조회수
8
답변 완료

* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.

* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.



앱스크립트 코드 삽입 후 자동화 실행 시 아래와 같은 오류 메시지가 나옵니다.


Exception: Unexpected error while getting the method or property getFolderById on object DriveApp.


앱스크립트 화면에서 실행해보니 TypeError: Cannot read properties of undefined (reading 'values') onFormSubmit @ Code.gs:5

에러가 나옵니다.


챗지피티에게 물어보니 트리거를 추가하라는데 트리거 추가해도 해결이 안 됩니다.






작성한 코드 및 에러 메세지

// 구글 폼을 제출하면 추적하여 이메일 알림 발송하는 함수

function onFormSubmit(e) {


// 구글 폼의 응답을 찾아내서 변수로 지정

let formResponse = e.values;


// console.log(formResponse);


let timeStamp = formResponse[0];

let email = formResponse[1];

let name = formResponse[2];

let birth = formResponse[3];

let phone = formResponse[4];

let job = formResponse[5];

let requestDate = formResponse[6];

let requestTime = formResponse[7];


// 메일 발송에 필요한 정보 찾기

let myMail = '내 이메일 주소';

let mailTitle = '[면접 일정 확인 요청] 지원자가 구글 폼을 작성했어요!';


// HTML 메일 형태로 데이터 담기

let mailBody = `<div>

<h3>${mailTitle}</h3>

<p>작성시간 : ${timeStamp}</p>

<p>성함 : ${name}</p>

<p>생년월일 : ${birth}</p>

<p>희망직무 : ${job}</p>

<p>이메일 : ${email}</p>

<p>전화번호 : ${phone}</p>

<p>면접 희망일자 : ${requestDate}</p>

<p>면접 희망시각 : ${requestTime}</p>

<a href="내 구글 시트 URL">면접 신청 시트 확인하기</a>

</div>`;


// 메일로 데이터 전송

sendEmail(myMail, mailTitle, mailBody);

}


// 지메일을 보내는 함수

function sendEmail(recipient, subject, body) {


MailApp.sendEmail({

to: recipient,

subject: subject,

htmlBody: body

});

}


// 면접 사실 확인서를 만드는 함수

function createInterviewDocument(data) {


let name = data[0];

let birth = data[1];

let job = data[2];

let interviewDate = data[3];

let today = new Date(Date.now())

let writeDate = Utilities.formatDate(today, Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm');


// // 템플릿 문서 ID (구글 문서에서 File -> Document Settings -> 문서 ID를 확인할 수 있음)

let templateDocId = '1xCDVNoogxlzoDahVBylEBBNjtXy7-h12E7kGGBQsqfw';


// // 템플릿 문서 복사

let newDoc = DriveApp.getFileById(templateDocId).makeCopy(name + " 면접 일정 안내서");

let newDocId = newDoc.getId();


// // 문서 열기

let doc = DocumentApp.openById(newDocId);


// // 변수로 대체할 내용 정의

let replaceMap = {

'{{name}}': name,

'{{interviewDate}}': interviewDate,

'{{jobTitle}}': job,

'{{writeDate}}': writeDate,

'{{birth}}': birth

};


// // 템플릿 내용을 변수로 대체하고 스타일 유지

replaceTextWithMapAndStyle(doc, replaceMap);


// // 문서 저장

doc.saveAndClose();


// // 공유할 드라이브 폴더의 ID

let folderId = '1rLLP5xg1A6q0kH1WBJO57iPy6szVcKfH?ths=true';


// // 문서 이동

DriveApp.getFileById(newDocId).moveTo(DriveApp.getFolderById(folderId));


// // 문서를 공유

DriveApp.getFileById(newDocId).setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);


// // 생성한 문서 반환

return { docId: newDocId, docLink: newDoc.getUrl() };

}


function replaceTextWithMapAndStyle(doc, replaceMap) {

for (let key in replaceMap) {

let searchText = key;

let newText = replaceMap[key];


// 문서에서 특정 스타일을 가진 텍스트 찾기

let searchResult = doc.getBody().findText(searchText);


while (searchResult) {

let foundText = searchResult.getElement().asText();


// 찾은 텍스트를 새로운 텍스트로 교체

foundText.replaceText(searchText, newText);


// 찾은 텍스트의 스타일 유지 (예시로 볼드 스타일을 유지함)

foundText.setBold(true);


// 다음 찾기

searchResult = doc.getBody().findText(searchText, searchResult);

}

}

}



// 구글 시트가 열리면 실행되는 함수

function onOpen() {

let ui = SpreadsheetApp.getUi();

ui.createMenu('자동화')

.addItem('일정 예약하기', 'createCalendarSchedule')

.addToUi();

}


// 구글 일정 예약하기 버튼을 누르면 실행되는 함수

function createCalendarSchedule() {

let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

let sheet = spreadsheet.getActiveSheet();


let startRow = 2;

let numRows = sheet.getLastRow() - 1;

let dataRange = sheet.getRange(startRow, 1, numRows, 10);

let data = dataRange.getValues();


// console.log(data);


for (let i = 0; i < data.length; i++) {

let row = data[i];

// console.log(row);


let timeStamp = row[0];

let email = row[1];

let name = row[2];

let birth = row[3];

let phone = row[4];

let job = row[5];

let requestDate = row[6];

let requestTime = row[7];

let interviewDate = row[8];

let isReserved = row[9];


if (interviewDate === '') {

console.log('일정 예약 실패 : 면접 일정 데이터가 비어있습니다');

continue;

}

if (isReserved === '완료') {

console.log('일정 예약 실패 : 이미 예약이 완료된 일정입니다');

continue;

}



interviewDate = new Date(interviewDate);

// 날짜와 시간을 문자열로 변환하여 원하는 형식으로 출력

let formattedDate = Utilities.formatDate(interviewDate, Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm');


// 문서 작성 자동화

let docData = [name, birth, job, formattedDate];


// createInterviewDocument 호출

let interviewDocumentInfo = createInterviewDocument(docData);


// HTML 메일 형태로 데이터 담기

let office = '서울특별시 르탄대로 11길 8';

let mailTitle = '안녕하세요. [대박기획]입니다. 제출해주신 면접 일정이 확정되어 공유드립니다.';

let admin = '김대박';


let mailBody = `<div>

<h3>${mailTitle}</h3>

<p>성함 : ${name}</p>

<p>희망직무 : ${job}</p>

<p>면접일자 : ${formattedDate}</p>

<p>면접장소 : ${office}</p>

<p>면접 일정 안내서 : <a href="${interviewDocumentInfo.docLink}">스파르타코딩클럽 면접 일정 안내서</a></p>

<p>인사 담당자 ${admin} 드림</p>

</div>`


// 메일로 고객에게 데이터 전송

sendEmail(email, '[대박기획] 확정된 면접 일정 공유드립니다.', mailBody);


// startDate에 30분을 추가하여 endDate 생성

let endDate = new Date(interviewDate.getTime() + 30 * 60 * 1000);

let scheduleName = `${job}-${name} 님 면접`;

let mySchedules = CalendarApp.getDefaultCalendar().getEvents(interviewDate, endDate, { search: scheduleName });


// 중복된 스케쥴이 없으면 구글 캘린더 일정으로 추가

if (mySchedules.length === 0) {

CalendarApp.getDefaultCalendar().createEvent(scheduleName, interviewDate, endDate);

}


// 자동화 마무리 셀 데이터 채우기

let statusSheet = spreadsheet.getSheetByName("설문지 응답 시트1");

statusSheet.getRange(startRow + i, 10).setValue("완료");

console.log(`예약 완료 : ${job} 으로 지원한 ${name} 님의 일정 예약이 완료되었습니다`);


}

}




취소
 공유
취소
댓글 0
댓글 알림
나의얼굴