實作抗體鑑定細胞資料庫(2)-撰寫 Javascript 腳本
撰寫 Javascript 腳本
執行 App script 之前,都會跳出安全警示,確認使用者是否相信所執行的腳本。由於是自己寫的內容,當然可以相信,並忽略警告。
搜尋血球資料
搜尋流程大致可分為: 讀取搜尋條件 > 搜尋血球資料庫 > 顯示搜尋結果
function search() {
var sp = SpreadsheetApp.getActiveSpreadsheet();
var s = sp.getSheetByName("Search");
// 定位搜尋條件的範圍
var titleRow = getKeywordPos(s, "POS").getRow()-1;
var posRow = getKeywordPos(s, "POS").getRow();
var negRow = getKeywordPos(s, "POS").getRow()+1;
var startCol = getKeywordPos(s, "POS").getColumn()+1;
var lastColumn = s.getLastColumn();
var keys = s.getRange(titleRow,1,1, lastColumn).getValues()[0];
// 讀取條件
var filter={};
filter["positive"] = [];
filter["negative"] = [];
for(var col=startCol; col<= lastColumn; col++) {
//陽性條件
if(s.getRange(posRow, col).getValue()) {
filter["positive"].push(keys[col-1]);
}
//陰性條件
if(s.getRange(negRow, col).getValue()) {
filter["negative"].push(keys[col-1]);
}
}
// 是否搜尋用盡之血球
var showEmpty = getKeywordPos(s, "Show empty").offset(0,1).getValue();
// 定位填入資料位置
var startCol = getKeywordPos(s, "Select").getColumn();
var titleRow = getKeywordPos(s, "Select").getRow();
//讀取所有血球頁籤
var cellSheets = getCellSheets();
for(i in cellSheets) {
var data = getData(cellSheets[i], filter, showEmpty);
var startRow = s.getLastRow()+1;
var startPos = s.getRange(startRow, startCol);
filldata(s, titleRow, startPos,data);
}
}
search()
裡面自訂的 function
如下:
getKeywordPos()
/*
回傳 Keyword 位置
*/
function getKeywordPos(sheet, keyword) {
var search = sheet.createTextFinder(keyword);
var range = search.findNext();
return range;
}
主要是拿來定位用。找出特定關鍵定的位置。例如在 Search
頁籤中,找到 POS 的位置,就可以推算出抗原表題、陽性條件跟陰性條件的相對位置。
getCellsheets()
/*
讀取細胞頁籤
*/
function getCellSheets() {
var sp = SpreadsheetApp.getActiveSpreadsheet();
var sheets = sp.getSheets();
var cellSheets=[];
// 讀取名為 "H-hide" 的頁籤,裡面紀錄非血球資料的頁籤
var hideSheet = sp.getSheetByName("H-hide");
var toHide =hideSheet.getRange(1, 1, hideSheet.getLastRow()).getValues();
for(i in sheets) {
var skip = false;
var sheetName =sheets[i].getName();
if(sheetName.indexOf("H-") ==0) continue; //略過所有開頭為 "H-" 的頁籤
// 略過非血球資料的頁籤
for(i2 in toHide) {
if(sheetName == toHide[i2][0]) skip=true;
}
if(skip) continue;
cellSheets.push(sheets[i]);
}
return cellSheets;
}
getData()
/*
試取細胞 sheet 內,血球表現型的資料。
filter: 抗原篩選器
includeEmpty: 是否搜尋已用盡之細胞試劑
*/
function getData(sheet, filter, includeEmpty) {
var targetPos = getKeywordPos(sheet, "cell#");
var titleRow = targetPos.getRow();
var lastColumn = sheet.getLastColumn();
var lastRow=sheet.getLastRow();
var keys = sheet.getRange(titleRow,1,1, lastColumn).getValues()[0];
var res=[]; //最後的搜到的血球
for(var row=titleRow+1; row<=lastRow;row++){
var data = {}; // 每一筆血球之表現型資料
for(var col=1; col<=lastColumn; col++){
var cellValue = sheet.getRange(row, col).getValue();
data[keys[col-1]] = cellValue;
}
// 判斷是否搜尋用盡的血球
if(!includeEmpty && data["Out"]==true){continue;}
var toAdd = true;
// 過濾陽性血球,非陽性排除
for(pos in filter["positive"]){
if(data[filter["positive"][pos]] != "+" && data[filter["positive"][pos]] != "+s" && data[filter["positive"][pos]] != "w") {
toAdd=false;
break;
}
}
// 過濾陰性血球,非陰性排除
for(neg in filter["negative"]) {
if(data[filter["negative"][neg]] != "0") {
toAdd=false;
break;
}
}
if(toAdd) res.push(data);
}
return res;
}
fillData()
/**
* sheet: 填入的頁籤
* titleRow: 表填入格之表頭列
* startPos: 填入位置
* data: 欲填入之血球資料
*/
function filldata(sheet, titleRow, startPos, data) {
var s = sheet
var startCol = startPos.getColumn();
var lastColumn = s.getLastColumn();
var startRow = startPos.getRow();
var keys = s.getRange(titleRow,1,1, lastColumn).getValues()[0];
for(var row in data) {
// 計算填入的列
var targetRow = parseInt(startRow) + parseInt(row);
// 略過未選擇之血球
if(data[row]["Select"] != null && data[row]["Select"] !=true) {
startRow -=1;
continue;
}
for(var col= startCol;col<=lastColumn;col++) {
// 當表頭無名稱時停止
if(keys[col-1] == "") {
break;
}
// 在 select 欄位加上 checkbox
if(keys[col-1] == "Select") {
if(!data[row]["Out"]) {
s.getRange(targetRow, col).insertCheckboxes();
} else{
s.getRange(targetRow, col).setValue("X"); // 當血球用完時顯示"X"
}
continue;
}
// 填入資料
var value=data[row][keys[col-1]];
if(value==null) {
value ="/"; //當無表現型資料時顯示"/"
}
s.getRange(targetRow, col).setValue(value);
}
}
}
匯出選取血球為 Panel 表
匯出流程:建立空白 Panel 表 > 讀取搜尋結果 > 將血球資料填入空白 Panel 表中
function exportCells() {
// 建立空白 Panel 表
var outSheet = createEmptyPanel("H-emptySelect");
var sp = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = sp.getSheetByName("Search")
sortSearchData(); // 排序血球之巨集
var data = getData(sourceSheet, {}, false);
data = cleanData(data);
var targetRange = getKeywordPos(outSheet, "LOT");
var titleRow = targetRange.getRow();
var startPos = targetRange.offset(1,0);
filldata(outSheet, titleRow, startPos , data);
}
createEmptyPanel()
/*
* 複製空白 Panel 表
* emptySheetName: 空白 Panel 表樣版頁籤
**/
function createEmptyPanel(emptySheetName) {
var sp = SpreadsheetApp.getActiveSpreadsheet();
var outSheet = sp.getSheetByName("Out");
if (outSheet!=null) sp.deleteSheet(outSheet);
var tempSheet = sp.getSheetByName(emptySheetName);
outSheet = tempSheet.copyTo(sp);
outSheet.setName("Out");
sp.setActiveSheet(outSheet);
sp.moveActiveSheet(2);
return outSheet;
}
sortSearchData()
/*
* 將已選擇的血球置頂,並依日期排序
* 基本上是用巨集產生的
*/
function sortSearchData() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Search");
var row = getKeywordPos(spreadsheet, "Select").getRow();
var range = spreadsheet.getRange(row, 1, 100, 35 );
range.offset(1, 0, range.getNumRows() - 1).sort([{column: 1, ascending: false},{column: 4, ascending: false}, {column: 2, ascending: true}]);
};
cleanData()
/*
* 修改格式
* */
function cleanData(dataArray) {
for(var idx in dataArray) {
dataArray[idx]["Expiration date"] =Utilities.formatDate(dataArray[idx]["Expiration date"], "GMT+8", "yyyyMMdd");
dataArray[idx]["LOT-cell#"] = dataArray[idx]["LOT"].toString() +"-"+ dataArray[idx]["cell#"].toString();
}
return dataArray;
}
待續….
關鍵字: 抗體鑑定, 血庫, Javascript, Google sheets, Apps script
留言
張貼留言