GitãšGASã§ã¹ãã¬ããã·ãŒããå®å šèªåã§å®æ管çããæé ã¬ã€ã ð
ããã«ã¡ã¯ããšã³ãžãã¢ããã§ãïŒ
æ¬èšäºã§ã¯ãGoogle Apps ScriptïŒGASïŒãšGitïŒããã§ã¯GitHubãäŸã«ããŸãïŒãçµã¿åãããã¹ãã¬ããã·ãŒãã®ããŒã¿ãèªåã§å®æçã«ç®¡çã»æŽæ°ããæ¹æ³ã1ããäžå¯§ã«è§£èª¬ããŠãããŸããããã«ãããããšãã°å®æçãªããŒã¿ã®ããã¯ã¢ãããå±¥æŽç®¡çããããŠããŒã ã§ã®å
±æãã¹ã ãŒãºã«è¡ããŸãã
ç®æ¬¡
- ã¯ããã«ïŒå šäœã®æµã
- å¿ èŠãªæºå
- Google Apps Scriptãããžã§ã¯ãã®äœæãšèšå®
- ã¹ãã¬ããã·ãŒãããŒã¿ã®ååŸãšå€æ
- GitHub APIã䜿ã£ãŠèªåã³ããã
- å®æå®è¡ããªã¬ãŒã®èšå®
- å šäœãããŒå³
- ãŸãšã
ã¯ããã«ïŒå šäœã®æµã
GitãšGASãé£æºããããšã§ã以äžã®ãããªããã»ã¹ãèªååãããŸãã
- ã¹ãã¬ããã·ãŒãïŒå®æçã«ææ°ã®ããŒã¿ãååŸ
- GASïŒããŒã¿ãCSVãªã©ã®ããã¹ã圢åŒã«å€æããããŒã¹64ãšã³ã³ãŒã
- GitHub APIïŒGASããPUTãªã¯ãšã¹ããçšããŠãGitãªããžããªå ã®ãã¡ã€ã«ãæŽæ°ïŒâ»ãã§ã«ååšããå Žåã¯æŽæ°ããªããã°æ°èŠäœæïŒ
- å®æããªã¬ãŒïŒGASã®æéããŒã¹ããªã¬ãŒã«ãããäžèšããã»ã¹ãèªåå®è¡
ãã®èªååã«ããã誰ããã€ã©ã®ãããªå€æŽãå ãããã®å±¥æŽãGitäžã§ç®¡çã§ããããŒã ã§ã®å ±æãããã¯ã¢ããã容æã«ãªããŸãã
å¿ èŠãªæºå
GitHubã¢ã«ãŠã³ããšãªããžããªã®äœæ
- GitHubã«ãµã€ã³ã¢ããããã¢ã«ãŠã³ããååŸããŠãã ããã
- ãNew repositoryããããæ°èŠãªããžããªïŒäŸïŒ
spreadsheet-backup
ïŒãäœæããŸãã
â»å ¬éã»éå ¬éã¯ãããžã§ã¯ãã«å¿ããŠéžãã§ãã ããã
ããŒãœãã«ã¢ã¯ã»ã¹ããŒã¯ã³ã®ååŸ
GitHub APIã§èªèšŒãããããããŒãœãã«ã¢ã¯ã»ã¹ããŒã¯ã³ïŒPATïŒãå¿ èŠã§ãã
- GitHubäžã§ãSettingsãâãDeveloper settingsãâãPersonal access tokensãã«ç§»åã
- ãGenerate new tokenããã¯ãªãã¯ãã以äžã®ã¹ã³ãŒãã«ãã§ãã¯ãå
¥ããŠçæããŠãã ããïŒ
-
repo
ïŒãªããžããªã®èªã¿æžãæš©éïŒ
-
- çºè¡ãããããŒã¯ã³ã¯åŸã§GASã®ã³ãŒãã«èšå®ããŸãã®ã§ãæ§ããŠãããŸãããã
Google Apps Scriptãããžã§ã¯ãã®äœæãšèšå®
- Google DriveãŸãã¯Google Apps Scriptã«ã¢ã¯ã»ã¹ããæ°ãããããžã§ã¯ããäœæããŸãã
- ãããžã§ã¯ãåããSpreadsheet Git Backupããªã©ãåãããããå称ã«å€æŽããŸãã
ã¹ãã¬ããã·ãŒãããŒã¿ã®ååŸãšå€æ
ãã®äŸã§ã¯ãã¹ãã¬ããã·ãŒãã®ãããŒã¿ããšããã·ãŒãã®å 容ãCSV圢åŒã«å€æããŸãã
-
æé
- ã¹ãã¬ããã·ãŒãã®å¯Ÿè±¡ã·ãŒããååŸ
- ã·ãŒãå ã®å šããŒã¿ã2次å é åãšããŠååŸ
- è¡ããšã«ã«ã³ãåºåãã«å€æããå šäœãæ¹è¡ã§é£çµ
- çæãããããã¹ããBase64ãšã³ã³ãŒã
以äžã¯ãµã³ãã«ã³ãŒãã®äžéšã§ãã
/**
* ã¹ãã¬ããã·ãŒãããããŒã¿ãååŸããCSV圢åŒã®Base64æååã«å€æããé¢æ°
*/
function getCSVData() {
// ã·ãŒãåãæå®ïŒäŸïŒ"ããŒã¿"ïŒ
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ããŒã¿");
var data = sheet.getDataRange().getValues();
// CSV圢åŒã«å€æïŒåè¡ãã«ã³ãã§é£çµããè¡ããšã«æ¹è¡ïŒ
var csv = data.map(function(row) {
// ã»ã«å
ã®ã«ã³ãããšã¹ã±ãŒãïŒå¿
èŠã«å¿ããŠïŒ
return row.map(function(cell) {
return '"' + String(cell).replace(/"/g, '""') + '"';
}).join(",");
}).join("\n");
// Base64ãšã³ã³ãŒã
var encodedCSV = Utilities.base64Encode(csv);
return encodedCSV;
}
GitHub APIã䜿ã£ãŠèªåã³ããã
Google Apps Scriptã®UrlFetchApp
ãå©çšããŠãGitHub APIçµç±ã§ãªããžããªå
ã®ãã¡ã€ã«ãæŽæ°ããŸãã
GitHub APIã§ã¯ãæ¢åãã¡ã€ã«ã®æŽæ°ã®å ŽåãçŸåšã®ãã¡ã€ã«ã®SHAãå¿
èŠãšãªãããããŸãGETãªã¯ãšã¹ãã§ãã¡ã€ã«ã®æ
å ±ãååŸãããã®SHAãå©çšããŠPUTãªã¯ãšã¹ããçºè¡ããŸãã
以äžã¯ãã¹ãã¬ããã·ãŒãã®CSVããŒã¿ãGitHubã«ã³ãããããããã®ãµã³ãã«ã³ãŒãã§ãã
/**
* ã¹ãã¬ããã·ãŒãã®å
容ãGitHubãªããžããªã«ã³ãããããé¢æ°
*/
function updateSpreadsheetToGitHub() {
// â CSVããŒã¿ãååŸ
var encodedContent = getCSVData();
// â¡ GitHubãªããžããªã®æ
å ±ãèšå®
var owner = "yourusername"; // GitHubã®ãŠãŒã¶ãŒåã«çœ®ãæãã
var repo = "spreadsheet-backup"; // äœæãããªããžããªåã«çœ®ãæãã
var path = "data.csv"; // ãªããžããªå
ã®ãã¡ã€ã«ãã¹
var url = "https://api.github.com/repos/" + owner + "/" + repo + "/contents/" + encodeURIComponent(path);
var token = "YOUR_GITHUB_PAT"; // ååŸããããŒãœãã«ã¢ã¯ã»ã¹ããŒã¯ã³ã«çœ®ãæãã
// ⢠ããããŒã®èšå®
var headers = {
"Authorization": "token " + token,
"Accept": "application/vnd.github.v3+json"
};
// ⣠æ¢åãã¡ã€ã«ã®SHAãååŸïŒæ¢ã«ãã¡ã€ã«ãããå ŽåïŒ
var sha = "";
var options = {
"method": "get",
"headers": headers,
"muteHttpExceptions": true
};
var response = UrlFetchApp.fetch(url, options);
if (response.getResponseCode() === 200) {
var respObj = JSON.parse(response.getContentText());
sha = respObj.sha;
Logger.log("æ¢åã®ãã¡ã€ã«SHAãååŸ: " + sha);
} else {
Logger.log("ãã¡ã€ã«ãååšããªãããååã³ãããã§ãã");
}
// †ã³ãããçšã®ãã€ããŒãäœæ
var payload = {
"message": "Update spreadsheet data " + new Date().toISOString(),
"committer": {
"name": "Your Name", // èªåã®ååã«çœ®ãæã
"email": "your.email@example.com" // èªåã®ã¡ãŒã«ã¢ãã¬ã¹ã«çœ®ãæã
},
"content": encodedContent
};
// æ¢åãã¡ã€ã«æŽæ°ã®å ŽåãSHAãå¿
èŠ
if (sha) {
payload.sha = sha;
}
// ⥠PUTãªã¯ãšã¹ãã®ãªãã·ã§ã³èšå®
options = {
"method": "put",
"headers": Object.assign(headers, {"Content-Type": "application/json"}),
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
// ⊠APIãªã¯ãšã¹ãéä¿¡
var putResponse = UrlFetchApp.fetch(url, options);
Logger.log("æŽæ°çµæ: " + putResponse.getContentText());
}
泚æç¹ïŒ
- äžèšã³ãŒãå
ã®
yourusername
ãspreadsheet-backup
ãYOUR_GITHUB_PAT
ãããã³ã³ããã¿ãŒæ å ±ã¯åèªã®ç°å¢ã«åãããŠå€æŽããŠãã ããã - GitHub APIã®ã¬ã¹ãã³ã¹ã³ãŒãïŒ200ã®å Žåã¯æ¢åãã¡ã€ã«ããã404ã®å Žåã¯æ°èŠäœæãªã©ïŒããã§ãã¯ãããšã©ãŒãã³ããªã³ã°ãé©å®è¡ããŸãããã
å®æå®è¡ããªã¬ãŒã®èšå®
GASã§ã¯ãæéããŒã¹ã®å®è¡ããªã¬ãŒãèšå®ããããšã§ãèªåã§ã¹ã¯ãªãããå®æå®è¡ã§ããŸãã
- GASãšãã£ã¿äžéšã®ãæèšã¢ã€ã³ã³ïŒããªã¬ãŒïŒããã¯ãªãã¯ãããã
ã¡ãã¥ãŒãããç·šéãâãçŸåšã®ãããžã§ã¯ãã®ããªã¬ãŒããéžæããŸãã - ãããªã¬ãŒãè¿œå ããã¿ã³ãã¯ãªãã¯ã
- 以äžã®èšå®äŸã®ããã«èšå®ããŸãïŒ
-
å®è¡ããé¢æ°ïŒ
updateSpreadsheetToGitHub
- ã€ãã³ãã®ãœãŒã¹ïŒ æéäž»å°å
- ã¿ã€ãïŒ æ¥æ¬¡ããããã¯ä»»æã®ééïŒäŸïŒ1æéããšïŒ
-
å®è¡ããé¢æ°ïŒ
- ä¿åããŠçµäºã
ããã§ãèšå®ããæéééã§èªåçã«ã¹ãã¬ããã·ãŒãã®å 容ãGitHubã«ã³ããããããããã«ãªããŸããâ°
å šäœãããŒå³
以äžã®å³ã¯å šäœã®ããã»ã¹ã®æµãã瀺ããŠããŸãã
ââââââââââââââââââââââââââââââââ
â Google ã¹ãã¬ããã·ãŒã â
â ïŒããŒã¿ã®å
¥åã»ç·šéïŒ â
âââââââââââââââ¬âââââââââââââââ
â
â ãGASã§å®æçã«å®è¡ã
âŒ
ââââââââââââââââââââââââââââââââ
â Google Apps Script â
â ã»ããŒã¿ååŸã»CSVå€æ â
â ã»Base64ãšã³ã³ãŒã â
â ã»GitHub APIã§PUTãªã¯ãšã¹ã â
âââââââââââââââ¬âââââââââââââââ
â
âŒ
ââââââââââââââââââââââââââââââââ
â GitHubãªããžã㪠â
â ã»data.csvæŽæ° â
â ã»ã³ãããå±¥æŽç®¡ç â
ââââââââââââââââââââââââââââââââ
ãŸãšã
æ¬èšäºã§ã¯ãGitHubãšGoogle Apps Scriptãçµã¿åãããã¹ãã¬ããã·ãŒãã®å
容ãèªåã§å®æçã«Gitãªããžããªã«ã³ãããããæé ã解説ããŸããã
äž»ãªæµãã¯ä»¥äžã®éãã§ãïŒ
-
æºå
GitHubäžã®ãªããžããªäœæãšããŒãœãã«ã¢ã¯ã»ã¹ããŒã¯ã³ã®ååŸ -
GASãããžã§ã¯ãã®äœæ
ã¹ãã¬ããã·ãŒãã®ããŒã¿ãååŸã»CSV圢åŒã«å€æããBase64ãšã³ã³ãŒã -
GitHub APIãå©çšããã³ãããåŠç
PUTãªã¯ãšã¹ããçšããŠæ¢åãã¡ã€ã«ã®æŽæ°ãŸãã¯æ°èŠäœæãå®æœ -
æéããªã¬ãŒã§èªåå®è¡
GASã®å®æå®è¡ããªã¬ãŒãèšå®ããŠã決ãŸã£ãæéã«ã¹ã¯ãªãããå®è¡
ããã«ãããã¹ãã¬ããã·ãŒãã®å€æŽå±¥æŽãGitäžã«èªåã§èšé²ãããããã¯ã¢ãããããŒã å ±æãã¹ã ãŒãºã«è¡ããŸãããã²ãã®æé ãåèã«ãããªãã®ãããžã§ã¯ãã§ãèªå管çãå®è·µããŠã¿ãŠãã ããïŒ
Happy Coding! ð
ð ãæ¯æŽããã ããŸãããïŒ
ãã®ããã°ã§ã¯ãé«å質ãªæ å ±æäŸãšåŠç¿æŽ»åãéããŠãèªè ã®çããŸã®ã圹ã«ç«ã€ããšãç®æããŠããŸãããããã®èšäºã圹ç«ã£ããšæããŠããã ããŸãããããæ¯æŽããã ãããšå¹žãã§ãïŒ
æå·è³ç£ã«ããå¯ä»
以äžã®ãŠã©ã¬ããã¢ãã¬ã¹ããå©çšãã ãããéèŠïŒEthereum (ETH)ãBNB Chain (BNB)ãPolygon (MATIC)ãAvalanche (AVAX) ã¯ãå šãŠä»¥äžã®åäžã¢ãã¬ã¹ã䜿çšããŸãããééãããã¯ãŒã¯ã®éžæãééãããšè³éã倱ãããŸãïŒ ééæã«ã¯ã絶察ã«äœ¿çšãããããã¯ãŒã¯ïŒäŸ: ERC-20ãBEP-20ãPolygonãAvalanche C-ChainïŒãå¿ ãæ£ããéžæããŠãã ããã

Ethereum (ETH) ïŒãããã¯ãŒã¯: ERC-20ïŒ
0x5CDA2F68f59F641B00aD172475c3d5fC10321174

BNB Chain (BNB) ïŒãããã¯ãŒã¯: BEP-20ïŒ
0x5CDA2F68f59F641B00aD172475c3d5fC10321174

Polygon (MATIC) ïŒãããã¯ãŒã¯: PolygonïŒ
0x5CDA2F68f59F641B00aD172475c3d5fC10321174

Avalanche (AVAX) ïŒãããã¯ãŒã¯: Avalanche C-ChainïŒ
0x5CDA2F68f59F641B00aD172475c3d5fC10321174

Solana (SOL)
EnPFbqDbF67rU9mAPvfgh4YYtncJNbFQ9NLQ5R6z5S2f

Stellar (XLM) ã¡ã¢: å¿ èŠã«å¿ããŠå ¥åããŠãã ããã
GCSMWCACKVEZ737GZAV4AJRFL52ZZKVQ7M3B3KYY64JJGOAO2GDYKABO

Ripple (XRP) ã¿ã°: å¿ èŠã«å¿ããŠå ¥åããŠãã ããã
r1s4EASr3zQRrfpDA3ptTahezBhGo2hhN

Cardano (ADA)
addr1q8heq6ddw8rwlqa5hqlucnfk36arah9tzc8ajxvu83870h7lrre25wzq9yemex857we56cm0xu8tmxqvm8nykmtgsjdqavdpv7

Dogecoin (DOGE)
DRFZ9JhAk3DTtu1tV85cawekWNrm1vKm3H
è³éçšé
å¯ä»éã¯ä»¥äžã®ç®çã§æŽ»çšãããŠããã ããŸãïŒ
- ãµãŒããŒç¶æè²»ããã¶ã€ã³ããŒã«è³Œå ¥
- åŠç¿æŽ»åïŒãªã³ã©ã€ã³ã³ãŒã¹åè¬ã»æžç±è³Œå ¥ïŒ
- èªè åãç¡æã³ã³ãã³ãå¶äœ
ãååããã ããçããŸã«ã¯å¿ããæè¬ç³ãäžããŸãïŒ ð
è£è¶³æ å ±
-
Ethereum (ETH)ãBNB Chain (BNB)ãPolygon (MATIC)ãAvalanche (AVAX)ã«ã€ããŠ
äžèš4ã€ã®ãããã¯ãŒã¯ã¯åããŠã©ã¬ããã¢ãã¬ã¹ïŒ0x5CDA2F68f59F641B00aD172475c3d5fC10321174
ïŒã䜿çšããŸãããã ããééæã«ã¯ã絶察ã«äœ¿çšãããããã¯ãŒã¯ïŒäŸ: ERC-20ãBEP-20ãPolygonãAvalanche C-ChainïŒãå¿ ãæ£ããéžæããŠãã ããã -
USDCãUSDTãªã©ã®ã¹ããŒãã«ã³ã€ã³ãã察å¿ãããããã¯ãŒã¯çµç±ã§ããã°ééå¯èœã§ãããã ããééå ã®ãããã¯ãŒã¯ãšéžæãããããã¯ãŒã¯ãäžèŽããŠããããšãå¿ ã確èªããŠãã ããã
-
ååééæã«ã¯å°é¡ã§ãã¹ãééããããšãããããããŸãã