function runExample() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// 従業員情報の保存されているセル範囲を取得
var employeeDataRange = ss.getRangeByName("employeeData");
// 従業員データのすべての行に対して従業員オブジェクトを生成
var employeeObjects = getRowsData(sheet, employeeDataRange);
var thirdEmployee = employeeObjects[2];
var stringToDisplay = "The third row is: " + thirdEmployee.firstName + " " + thirdEmployee.lastName;
stringToDisplay += " (id #" + thirdEmployee.employeeId + ") working in the ";
stringToDisplay += thirdEmployee.department + " department and with phone number ";
stringToDisplay += thirdEmployee.phoneNumber;
Browser.msgBox(stringToDisplay);
}
function runExercise() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[1];
// 従業員情報の保存されているセル範囲を取得
var employeeDataRange = sheet.getRange("B1:F5");
// 従業員データのすべての行に対して従業員オブジェクトを生成
var employeeObjects = getColumnsData(sheet, employeeDataRange);
var thirdEmployee = employeeObjects[2];
var stringToDisplay = "The third column is: " + thirdEmployee.firstName + " " + thirdEmployee.lastName;
stringToDisplay += " (id #" + thirdEmployee.employeeId + ") working in the ";
stringToDisplay += thirdEmployee.department + " department and with phone number ";
stringToDisplay += thirdEmployee.phoneNumber;
ss.msgBox(stringToDisplay);
}
function getRowsData(sheet, range, columnHeadersRowIndex) {
columnHeadersRowIndex = columnHeadersRowIndex || range.getRowIndex() - 1;
var numColumns = range.getEndColumn() - range.getColumn() + 1;
var headersRange = sheet.getRange(columnHeadersRowIndex, range.getColumn(), 1, numColumns);
var headers = headersRange.getValues()[0];
return getObjects(range.getValues(), normalizeHeaders(headers));
}
// getColumnsData は入力された行範囲をループしてオブジェクト配列を返す
// それぞれのオブジェクトは行に与えられたすべてのデータを含み、正規化されたカラム名によってインデックス化される
// Arguments:
// - sheet: 処理すべきデータをもつシートオブジェクト
// - range: データが保存されている正確なセル範囲
// - rowHeadersColumnIndex: は行名の保存されているカラム番号を指定する
// この引数はオプション。デフォルトは範囲の左隣のカラムに決まる
// 配列オブジェクトを返す
function getColumnsData(sheet, range, rowHeadersColumnIndex) {
rowHeadersColumnIndex = rowHeadersColumnIndex || range.getColumnIndex() - 1;
var headersTmp = sheet.getRange(range.getRow(), rowHeadersColumnIndex, range.getNumRows(), 1).getValues();
var headers = normalizeHeaders(arrayTranspose(headersTmp)[0]);
return getObjects(arrayTranspose(range.getValues()), headers);
}
// データの中のあらゆる行データについてデータを持つオブジェクトが生成される
// オブジェクトフィールドの名前はそれぞれkeyとして定義される
// 引数:
// - data: JavaScript 二次配列
// - keys: 生成すべきオブジェクトが持つプロパティ名を定義付ける文字列の配列
function getObjects(data, keys) {
var objects = [];
for (var i = 0; i < data.length; ++i) {
var object = {};
var hasData = false;
for (var j = 0; j < data[i].length; ++j) {
var cellData = data[i][j];
if (isCellEmpty(cellData)) {
continue;
}
object[keys[j]] = cellData;
hasData = true;
}
if (hasData) {
objects.push(object);
}
}
return objects;
}
// 正規化された文字列の配列を返す
// 引数:
// - headers: 正規化すべき文字列配列
function normalizeHeaders(headers) {
var keys = [];
for (var i = 0; i < headers.length; ++i) {
var key = normalizeHeader(headers[i]);
if (key.length > 0) {
keys.push(key);
}
}
return keys;
}
// 単語に分けるためにすべての英数字を破棄し小文字を利用して文字を正規化する
// アウトプットはいつも小文字で始まる
// この関数はJavaScript objectのオブジェクトプロパティ名を作るようにデザインされている
// 引数:
// - header: 正規化すべき文字列
// 例:
// "First Name" -> "firstName"
// "Market Cap (millions) -> "marketCapMillions
// "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
function normalizeHeader(header) {
var key = "";
var upperCase = false;
for (var i = 0; i < header.length; ++i) {
var letter = header[i];
if (letter == " " && key.length > 0) {
upperCase = true;
continue;
}
if (!isAlnum(letter)) {
continue;
}
if (key.length == 0 && isDigit(letter)) {
continue; // first character must be a letter
}
if (upperCase) {
upperCase = false;
key += letter.toUpperCase();
} else {
key += letter.toLowerCase();
}
}
return key;
}
// 読み込まれたセルデータが空のときtrueを返す
// 引数:
// - cellData: 文字列
function isCellEmpty(cellData) {
return typeof(cellData) == "string" && cellData == "";
}
// 文字chrがアルファベット順ならばtrue、そうでないならfalseを返す
function isAlnum(char) {
return char >= 'A' && char <= 'Z' ||
char >= 'a' && char <= 'z' ||
isDigit(char);
}
// 文字が数字ならtrue、そうでないならfalseを返す
function isDigit(char) {
return char >= '0' && char <= '9';
}
// JavaScript二次配列を与えられたこの関数は転置(入れ替え)表を返す
// 引数:
// - data: JavaScript二次配列
// JavaScript二次配列を返す
// 例: Transpose配列([[1,2,3],[4,5,6]]) は [[1,4],[2,5],[3,6]]を返す
function arrayTranspose(data) {
if (data.length == 0 || data[0].length == 0) {
return null;
}
var ret = [];
for (var i = 0; i < data[0].length; ++i) {
ret.push([]);
}
for (var i = 0; i < data.length; ++i) {
for (var j = 0; j < data[i].length; ++j) {
ret[j][i] = data[i][j];
}
}
return ret;
}