본문 바로가기
Apps Script/Sheets

[GAS:sheets]CSV출력하기 / 1. 시트를 CSV형식으로 변환하기

by yunexus 2023. 1. 2.

CSV출력하기 목차

  1. 시트를 CSV형식으로 변환하기 (현재 열람중)
  2. 구글 드라이브에 CSV파일을 출력하기

1. 시트를 CSV로 변환하기

(1) CSV형식의 스프레드 시트를 작성 또는 준비한다.

     시트이름은 CSV 로 작성

그림 1-1

 

 

(2) Apps Script에서 코드를 작성한다.

     이하 사양에 대해 간단하게 정리

      변환할 시트이름으로 ActiveSpreadsheet를 가져온다

      1행 : Header 헤더

      2행부터 : data 데이터

      헤더와 데이터는 A열 부터 입력된다.

      헤더의 길이만큼 데이터를 출력한다. (헤더가 5개인 경우, 데이터는 E열까지 출력)

      데이터가 하나도 없는 행이 있다면 그 이후는 출력하지 않음.

      이외 체크처리는 없음.

const SHEET_CSV = getSheetByName('CSV');
const CELL_HEADER_FIRST = 'A1';
const CELL_DATE_FIRST = 'A2';
const STR_LINEFEED = '\n'; // UNIX, Linux, Mac
const STR_CARRIAGERETURN = '/r' // Mac OS X 이외의 Mac (Mac OS X 以外の Mac)
const STR_CARRIAGERETURN_LINEFEED = '\r\n'; // Windows
const STR_DOUBLE_QUOTATION = '\"';
const STR_COMMA = ',';
const STR_COLON = ':';
const INDEX_ZERO = 0;

// 스트레드시트에서 실행할 main function
function runPrintCSV() {
  let ui = SpreadsheetApp.getUi();
  let response = ui.alert("CSV를 출력합니까?", ui.ButtonSet.YES_NO);
  if (ui.Button.YES == response) {
    let csv = createCsvString(SHEET_CSV);
    ui.alert(csv);
  }
}

// CSV String 구하기
// @param ActiveSpreadSheet worksheet
// @return String csv
function createCsvString(workSheet) {
  let csv;
  let header = getHeaderValues(workSheet);
  let datas = getDataValues(workSheet, header.length - 1);
  csv = header.join(STR_COMMA);
  datas.forEach(data => {
    csv = csv.concat(STR_LINEFEED, data.join(STR_COMMA));
  });
  return csv;
}

// CSV의 Header값을 구하기
// @param ActiveSpreadSheet worksheet
// @return Array[Object] header header값
function getHeaderValues(workSheet) {
  let headerStartCell = workSheet.getRange(CELL_HEADER_FIRST);
  let headerEndCell = getRowEndCellHasValueFromRange(headerStartCell);
  let header = getRangeValuesWithCell(workSheet, headerStartCell, headerEndCell);
  return header.shift();
}

// CSV의 Data값을 구하기
// @param ActiveSpreadSheet worksheet
// @param int headerLength Header의 길이
// @return Array<Array<Object>> data data값
function getDataValues(workSheet, headerLength) {
  let dataStartCell = workSheet.getRange(CELL_DATE_FIRST);
  let dataEndCell = getColCellHasValueFromRange(dataStartCell, headerLength);
  let data = getRangeValuesWithCell(workSheet, dataStartCell, dataEndCell);
  return data;
}

// 시트 이름으로 ActiveSpreadsheet를 구하기
// @param String sheetName 시트 이름
// @return Sheet 시트 이름과 일치하는 시트 오브젝트
function getSheetByName(sheetName) {
  const activeSS = SpreadsheetApp.getActiveSpreadsheet();
  return activeSS.getSheetByName(sheetName);
}

// 행 가장 마지막 CELL을 구하기
// @param Range workRange 기준이되는 Range오브젝트
// @return Range cell 마지막 CELL
function getRowEndCellHasValueFromRange(workRange) {
  let cell;
  for (let index = 0; !workRange.offset(INDEX_ZERO, index).isBlank(); index++) {
    cell = workRange.offset(INDEX_ZERO, index);
  }
  return cell;
}

// 행X열의 가장 마지막 CELL을 구하기
// @param Range workRange 기준이되는 Range오브젝트
// @return Range cell 마지막 CELL
function getColCellHasValueFromRange(workRange, headerLength) {
  let cell;
  let hasColValue = false;
  for (let index = 0; ; index++) {
    for (let j = 0; j <= headerLength ; j++) {
      if (workRange.offset(index, j).isBlank()) continue;
      hasColValue = true;
      break;
    }
    // 행 값이 없으면 종료
    if (!hasColValue) break;
    cell = workRange.offset(index, headerLength);
    hasColValue = false;
  }
  return cell;
}

// a1Notation으로 Range의 값 구하기
// @param ActiveSpreadSheet worksheet
// @param Range startCell 좌측상단의 CELL
// @param Range endCell 우측하단의 CELL
// @return Array<Array<Object>> Range범위의 값
function getRangeValuesWithCell(workSheet, startCell, endCell) {
  let a1Notation = getA1Notation(startCell.getA1Notation(), endCell.getA1Notation());
  return workSheet.getRange(a1Notation).getValues();
}

// a1Notation의 그룹 구하기
// 예 fisrt = A1, second = B2, return = A1:B2
// @param Range first
// @param Range second 
// @return String
function getA1Notation(first, second) {
  return first + STR_COLON + second;
}

 

 

(3) runPrintCSV 함수를 실행해서 결과 확인하기

그림 1-2
그림 1-3

 

빈 셀은 공백으로 값이 표현되며 "," 로 구분자(delimite)가 들어가 있다.

8행은 값이 없으므로 이후 데이터는 출력하지 않음.

그림 1-4