업체에서 서로 다른 양식의 발주서를 받아 이를 하나의 송하인 양식으로 취합하는 업무를 합니다.
단순 반복적인 작업이 많아 실수할 위험이 있었고, 집중력이 떨어지면 더 많은 시간이 소요되었습니다.
이를 개선하고자 AI 도구를 활용해 자동화 프로세스를 만들어 보았습니다.
사용한 도구: ChatGPT, Google Apps Script
각 발주서는 CSV 형식이며, 헤더 이름도 파일마다 다를 수 있습니다.
예) 수령자명, 수취인명, 받는분, 수취인 주소, 주 소, 품목, 품명, 모델명 .. etc
내가 원하는 결과는 다음과 같습니다:
특정 열(예: 품목, 옵션, 수량)을 조합하여 하나의 열로 표시하고 싶습니다.
ex) 품목-청소기,옵션-화이트,수량-2 -> '청소기 화이트 2'우편번호와 전화번호는 맨 앞의 0이 사라지지 않도록 처리해야 합니다.
동일한 이름의 헤더(예: '우편번호')가 서로 다른 데이터를 포함하는 경우도 정확히 구분해야 합니다.
->(보내는분)우편번호,주소 와 (받는분)우편번호,주소는 동일한 헤더이지만 구분해야합니다.보내는 사람의 정보(우편번호, 주소 등)는 고정값으로 설정하고, 받는 사람의 정보는 각 CSV 파일에서 가져오도록 하고 싶습니다.
결과는 구글 스프레드시트에 저장되도록 설정해주세요.
(1) 연습용으로 두개의 발주서를 가지고 자동화 했습니다.
중앙에 숫자가 있는 컴퓨터 화면의 스크린샷
회색 배경에 흰색 선이 한 줄
(2) 송하인 양식에 맞춰 하나의 발주서를 통합하는 사례입니다.
컴퓨터 화면에 있는 텍스트 줄의 스크린샷
진행 과정:
1. ChatGPT로 Google Apps Script의 기초를 배우며 코드를 하나씩 작성했습니다.
한국어로 된 문자 메시지의 스크린샷
구글 앱스 스크립트 한국어로
하나씩 떠먹여 주는 지피티 유치원 선생님
구글 드라이브 코리아
한국어 문자 메시지 스크린샷
파일을 불러올수있도록 하는 파일 id를 url에서 찾는 법도 배웠습니다 .
러시아 비자 신청서 샘플
엑셀 업로드 했더니 와장창 깨져버린 모습
한국어로 된 Google 검색 페이지의 스크린샷
CSV 형식의 파일만 읽을 수 있다는 이야기를 듣구 머리털 나고 처음으로 csv 파일을 저장해보았습니다....만
역시나 계속되는 오류에 그만 정신을 잃고 말았습니다.
google app script라는 단어가 포함된 한국어 메시지
처음부터 알려달라고 빌었더니 그 후로 오류가 생기지 않더군요.
2. 여러 CSV 파일을 읽어와 원하는 송하인 양식으로 데이터를 취합하는 코드를 작성했습니다.
3. 작성한 Apps Script 코드는 아래와 같습니다.
function importAndMergeCSVForCustomOrder() {
// 1. 불러올 파일 이름 설정
var fileNames = ["h_commerce.csv", "custom.csv"];
// 2. 취합 문서의 열 순서 (기본 헤더)
var processedData = [["보내는분", "연락처1", "담당자", "핸드폰", "우편번호", "총주소",
"받는분", "연락처1", "담당자", "핸드폰", "우편번호", "총주소",
"수량", "품목", "운임타입", "지불조건", "출고번호",
"특기사항", "메모1", "메모2"]];
// 3. 보내는 사람의 기본 데이터 설정
var senderInfo = {
우편번호: "'00000", // 맨 앞 0이 유지되도록 문자열로 처리
총주소: "서울 어쩌구 어쩌로 19",
연락처1: "'0200000000",
핸드폰: "'01000000000"
};
// 4. 파일 처리
fileNames.forEach(function (fileName) {
var files = DriveApp.getFilesByName(fileName);
if (!files.hasNext()) {
Logger.log("파일을 찾을 수 없습니다: " + fileName);
return;
}
var file = files.next();
var csvData = Utilities.parseCsv(file.getBlob().getDataAsString());
var header = csvData[0];
// 열 위치 매핑
var columns = {};
header.forEach(function (colName, index) {
// 공백 제거 후 이름을 소문자로 비교
colName = colName.replace(/\s+/g, "").toLowerCase();
if (colName.includes("받는분") || colName.includes("수취인")) columns["받는분"] = index;
if (colName.includes("연락처") || colName.includes("전화번호")) columns["연락처1"] = index;
if (colName.includes("핸드폰") || colName.includes("모바일")) columns["핸드폰"] = index;
if (colName.includes("우편번호") || colName.includes("zip")) columns["받는우편번호"] = index;
if (colName.includes("주소")) columns["받는총주소"] = index;
if (colName.includes("수량") || colName.includes("개수")) columns["수량"] = index;
if (colName.includes("품명") || colName.includes("품목") || colName.includes("상품명")) columns["품목"] = index; // 품명 추가
if (colName.includes("옵션") || colName.includes("선택사항")) columns["옵션"] = index;
if (colName.includes("특기사항") || colName.includes("요청사항")) columns["특기사항"] = index;
});
// 데이터 처리
for (var i = 1; i < csvData.length; i++) {
var row = csvData[i];
// 빈 줄 건너뛰기
if (row.every(cell => !cell.trim())) continue;
// "품목" 데이터 조합
var itemDescription = [
columns["품목"] !== undefined ? row[columns["품목"]] : "",
columns["옵션"] !== undefined ? row[columns["옵션"]] : "",
columns["수량"] !== undefined ? row[columns["수량"]] : ""
].filter(Boolean).join(" ");
// "메모1" 데이터 조합
var memo1Content = [
columns["특기사항"] !== undefined ? row[columns["특기사항"]] : ""
].filter(Boolean).join(" / ");
var processedRow = [
// 보내는 사람 정보
"(주)000", // 보내는분
senderInfo.연락처1, // 연락처1
"", // 담당자
senderInfo.핸드폰, // 핸드폰
senderInfo.우편번호, // 우편번호 (보내는 사람)
senderInfo.총주소, // 총주소 (보내는 사람)
// 받는 사람 정보
row[columns["받는분"]] || "", // 받는분
row[columns["연락처1"]] ? `'${row[columns["연락처1"]]}` : "", // 연락처1
fileName.split(".")[0], // 담당자 (CSV 파일 이름 추가)
row[columns["핸드폰"]] ? `'${row[columns["핸드폰"]]}` : "", // 핸드폰
row[columns["받는우편번호"]] ? `'${row[columns["받는우편번호"]]}` : "", // 우편번호 (받는 사람)
row[columns["받는총주소"]] || "", // 총주소 (받는 사람)
// 주문 정보
row[columns["수량"]] || "", // 수량
itemDescription.trim(), // 품목: 품명 + 옵션 + 수량
"S", // 운임타입
"", // 지불조건
"", // 출고번호 (항상 공란)
"", // 특기사항 (항상 공란)
memo1Content, // 메모1
"" // 메모2 (항상 공란)
];
processedData.push(processedRow);
}
});
// 5. "orderlist" 스프레드시트 열기
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
sheet.clear();
// 6. 정리된 데이터 저장
sheet.getRange(1, 1, processedData.length, processedData[0].length).setValues(processedData);
Logger.log("CSV 데이터를 'orderlist' 시트에 취합 완료!");
}
한국어 한국어 한국어 한국어 한국어 한국어 한국어 한국어
custom.csv 와 h_commerce.csv 두개의 발주서가 하나의 송하인 양식으로 정리되었습니다.
결과와 배운 점
성과:
ChatGPT를 활용해 처음 접하는 Google Apps Script의 기초를 이해하고, 기본적인 자동화 스크립트를 작성할 수 있었습니다.
중복된 작업에서 발생하던 실수를 줄이고, 단순 반복 작업에서 시간을 절약할 가능성을 탐구했습니다.
어려움:
처음에는 Google Apps Script의 문법과 기본적인 개념을 전혀 몰라 어려움이 많았습니다. 특히 오류가 발생했을 때 그 의미를 이해하고 해결하는 데 시간이 걸렸습니다.
각 CSV 파일의 헤더 이름이 제각각이라 이를 모두 매핑하는 과정이 복잡하고 까다로웠습니다. 일부 양식은 손으로 직접 처리하는 것이 더 효율적이라는 생각도 들었습니다.
CSV 파일 변환과 스프레드시트 저장 등 새로운 작업 단계가 추가되면서 업무가 더 복잡하게 느껴지기도 했습니다.
앞으로의 개선 방향:
엑셀 파일 그 자체를 처리할 수 있는 자동화 도구를 사용하는 방향을 모색하고 싶습니다.