chevron_left

メインカテゴリーを選択しなおす

cancel
arrow_drop_down
  • プロパティの入出力

    function doGet(e) { var p = PropertiesService.getScriptProperties(); //スクリプトプロパティ用サービスの取得 var data = p.getProperty("TEST"); //プロパティの取り出し return ContentService.createTextOutput("設定した内容:"+data); } function setProperty(){ var p = PropertiesService.getScriptProperties(); p.setProperty("TEST","あいうえお"); //プロパティの設定 } 一回目はWEBから確認。二回目はsetPropertyを実行してからWEBで確認する。開発環境からプロパティを確認するには、ファイル -> プロジェクトプロパティ -> スクリプトプロパティを選ぶ

  • IDと日付を含んだ処理

    共通変数 ID処理 データ追加処理 データ追加テスト データの削除 データ削除テスト WEBアプリケーション化

  • GASとスプレッドシートの関数

    セルにフォーマットの適用

  • New

    サーバやプログラミングの技術情報

  • Java側

    class SendData{ public String name; public String msg; } class RecvData{ public int ret; public String[][] values; } public class MainActivity extends AppCompatActivity implements View.OnClickListener { final static String GAS_URL = ""; private EditText mEdit1; private EditText mEdit2; private TextView mText; Handler mHandler = new Handler(); private TextView mTextInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEdit1 = (EditText)findViewById(R.id.editText); mEdit2 = (EditText)findViewById(R.id.editText2); mText = (TextView)findViewById(R.id.textOutput); mTextInfo = (TextView)findViewById(R.id.textInfo); findViewById(R.id.button).setOnClickListener(this); findViewById(R.id.button2).setOnClickListener(this); recvData(); } @Override public void onClick(View v) { if(v.getId() ==

  • GASとAndroidプログラム(Java)2

    GAS側 レイアウト Java側 New

  • GAS側

    function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { var data = null; //POSTから送られてきているデータをオブジェクトに変換する if(e && e.postData) data = JSON.parse(e.postData.getDataAsString()); var retData = {}; //aとbを受け取る if(data && data.name!=null && data.msg!=null){ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample11").getActiveSheet(); //追加行の取得 var lastIndex = sheet.getLastRow()+1; //データを追加 //setValuesは二次元配列を利用する為、[[データ,データ],[データ,データ]]のような記述になる sheet.getRange(lastIndex,1,1,2).setValues([[data.name,data.msg]]); retData.ret = 1;//正常 } else{ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample11").getActiveSheet(); //シート内の全データを設定 if(sheet.getLastRow() > 0) retData.values = sheet.getRange(1,1,sheet.getLastRow(),2).getValues(); else retData.values = []; //データが無かった場合、空の配列を渡す retData.ret = 1;//正常 } //JSON文字列に変換 var j = JSON.stringi

  • WEBアプリケーション化

    function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { var data = null; //POSTから送られてきているデータをオブジェクトに変換する if(e && e.postData) data = JSON.parse(e.postData.getDataAsString()); var retData = {}; //データの確認 if(data && data.name!=null && data.msg!=null){ addMessage(data.name,data.msg); retData.ret = 1;//正常 }else if(data && data.del){ var id = parseInt(data.del); delMessage(id); retData.ret = 1;//正常 }else{ //スプレッドシートの取得 var sheet = openSheetFile(SHEET_NAME).getActiveSheet(); //シート内の全データを設定 if(sheet.getLastRow() > 0) retData.values = sheet.getRange(1,1,sheet.getLastRow(),4).getValues(); else retData.values = []; //データが無かった場合、空の配列を渡す retData.ret = 1;//正常 } //JSON文字列に変換 var j = JSON.stringify(retData); //結果を返す return ContentService.createTextOutput(j); }

  • 通信機能の分離

    void sendGas(final int a,final int b){ //通信はスレッドで行う必要がある Thread thread = new Thread(){ @Override public void run() { super.run(); //送信データの作成 SendData sendData = new SendData(); sendData.a = a; sendData.b = b; //GASに接続 RecvData recvData = Json.send(GAS_URL,sendData,RecvData.class); //データの表示 if(recvData != null) setText(""+recvData.anser); else setText("受信エラー"); } }; thread.start(); } onCreateでメソッドの呼び出しsendGas(20,30);

  • MainActivity.javaの編集

    //送信用データクラス class SendData{ int a; int b; } //受信用データクラス class RecvData{ int anser; } GASのアドレスを入れてくださいクラスのプロパティ final String GAS_URL=""; onCreateに追加 //通信はスレッドで行う必要がある Thread thread = new Thread(){ @Override public void run() { super.run(); //送信データの作成 SendData sendData = new SendData(); sendData.a = 10; sendData.b = 20; //GASに接続 RecvData recvData = Json.send(GAS_URL,sendData,RecvData.class); //データの表示 if(recvData != null) System.out.println(recvData.anser); else System.out.println("受信エラー"); } }; thread.start();

  • Androidのマニフェストの変更

    AndroidManifest.xmlで通信を許可する<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="・・・・"> <uses-permission android:name="android.permission.INTERNET"/> <application

  • Android側の準備

    EmptyActivityの作成jarライブラリの追加と、JsonクラスをMainActivityと同じ階層に作成

  • GAS側

    function doGet(e){ try{ return action(e); }catch(er){ Logger.log(er); } } function doPost(e){ try{ return action(e); }catch(er){ Logger.log(er); } } function action(e) { var data = null; //POSTから送られてきているデータをオブジェクトに変換する if(e && e.postData) data = JSON.parse(e.postData.getDataAsString()); var retData = {}; //aとbを受け取る if(data && data.a!=null && data.b!=null){ retData.anser = data.a + data.b; } //JSON文字列に変換 var j = JSON.stringify(retData); //結果を返す return ContentService.createTextOutput(j); }

  • GAS側

    function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { var ret; var jsonData = null; //POSTから送られてきているデータをオブジェクトに変換する if(e && e.postData) jsonData = JSON.parse(e.postData.getDataAsString()); //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample03").getActiveSheet(); if(jsonData && jsonData.msg){ //データが送られてきていたらスプレッドシートに出力 //データを追加 sheet.getRange(sheet.getLastRow()+1,1).setValue(jsonData.msg); ret = {"ret":1}; } else{ //データが送られてきていない場合、スプレッドシートの内容を返す //範囲指定で受け取る場合、カラムが一つでも二次元配列で返るので注意すること var values = sheet.getRange(1,1,sheet.getLastRow(),1).getValues(); ret = {"ret":1,"values":values}; } //JSON文字列として結果を返す return ContentService.createTextOutput(JSON.stringify(ret)); }

  • 単純なデータ

    GAS側function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { var data = null; //POSTから送られてきているデータをオブジェクトに変換する if(e && e.postData) data = JSON.parse(e.postData.getDataAsString()); if(data && data.name != null && data.age != null) log(data.name + ":"+data.age); //JSON文字列に変換 var j = JSON.stringify({"ret":1}); //結果を返す return ContentService.createTextOutput(j); } Java側class RetParam{ public int ret; } public class ExampleUnitTest { @Test public void test3() throws Exception { Data data = new Data(); data.name = "船橋太郎"; data.age = 20; RetParam param = Json.send("GASのアドレス",data,RetParam.class); if(param == null param.ret != 1) System.out.println("受信エラー"); else System.out.println("正常終了"); }}

  • JavaからGASへデータを送る

    単純なデータ

  • 配列

    GAS側function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { //配列データの作成 var list = []; list[0] = {"name":"aaa","age":20}; list[1] = {"name":"bbb","age":30}; list[2] = {"name":"ccc","age":100}; //出力用オブジェクトの作成 var datas = {}; datas.list = list; //JSON文字列に変換 var j = JSON.stringify(datas); //結果を返す return ContentService.createTextOutput(j); } Java側package to.pns.tbn.gastest; import android.bluetooth.BluetoothGattServer; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import java.io.DataOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.junit.Assert.*; class Data{ public String name; public int age; } class DataList{ public List<Data> list; } public class Exampl

  • GASからJavaにデータを送る

    単純データ 配列

  • 単純データ

    GASTest01(GAS側)function doGet(e){ return action(e); } function doPost(e){ return action(e); } function action(e) { //パラメータ用オブジェクトの作成 var data = {}; data.name = "aaa"; data.age = 20; //JSON文字列に変換 var j = JSON.stringify(data); //結果を返す return ContentService.createTextOutput(j); } ExampleUnitTest.javaclass Data{ public String name; public int age; } public class ExampleUnitTest { @Test public void addition_isCorrect() throws Exception { Data data = Json.send(GASのアドレス,null,Data.class); if(data == null) System.out.println("受信エラー"); else { System.out.println(data.name); System.out.println(data.age); } } }

  • Json用ライブラリの組み込み

    モジュールとして以下のものを追加dependencies { implementation 'com.fasterxml.jackson.core:jackson-core:2.8.8' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.8.8' implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.8' }Json.javapublic class Json{ public static <T> T send(String adress,Object obj, Class<T> valueType){ HttpURLConnection connection = null; StringBuilder sb = new StringBuilder(); try { //JSON用オブジェクトの作成 ObjectMapper mapper = new ObjectMapper(); //URLの設定 URL url = new URL(adress); connection = (HttpURLConnection)url.openConnection(); connection.setUseCaches(false); connection.setRequestMethod("POST"); connection.setInstanceFollowRedirects(true); connection.setRequestProperty("Content-Type", String.format("text/plain")); connection.setDoOutput(true); //オブジェクトをJSONデータに変換して出力 OutputStream os = co

  • 合計の計算

    function doGet(e){ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample02").getActiveSheet(); //データの読み込み var values = sheet.getRange(1,1,3,2).getValues(); //合計初期値0 var all = 0; //配列は0から開始 for(var i=0;i<3;i++) all += values[i][1]; //JSON文字列に変換 var j = JSON.stringify({"合計":all}); //データを戻す return ContentService.createTextOutput(j); }

  • データをまとめて取得

    function doGet(e){ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample02").getActiveSheet(); //データを読み込み var values = sheet.getRange(1,1,3,2).getValues(); //JSON文字列に変換 var j = JSON.stringify(values); //データを戻す return ContentService.createTextOutput(j); } 確認はWebアプリケーションとして行う。

  • データをまとめて出力2

    function myFunction(){ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample02").getActiveSheet(); //二次元配列の作成 var values = [["竹槍",3],["棍棒",8],["銅の剣",15]]; //データを書き込み sheet.getRange(8,10,3,2).setValues(values); return ContentService.createTextOutput("データを書き込みました"); }開始位置を変更しています。

  • データの検索

    function doGet(e){ var name = "棍棒"; //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample02").getActiveSheet(); //データを書き込み var values = sheet.getRange(1,1,3,2).getValues(); var i; for(i=0;i<3;i++) if(values[i][0] == name) break; //JSON文字列に変換 var j; if(i < 3) j = JSON.stringify({name:values[i][1]}); //注意 nameが棍棒として展開されない else j = JSON.stringify({"見つからない":0}); //データを戻す return ContentService.createTextOutput(j); }

  • データをまとめて出力

    function myFunction(){ //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample02").getActiveSheet(); //二次元配列の作成 var values = [["竹槍",3],["棍棒",8],["銅の剣",15]]; //データを書き込み sheet.getRange(1,1,3,2).setValues(values); return ContentService.createTextOutput("データを書き込みました"); } 範囲の取得方法getRange(開始行,開始列,行数,列数)取得した範囲に対してsetValuesを行うことにより、まとめてデータを書き込むことが出来ます。

  • スプレッドシートの操作

    function myFunction() { //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample01").getActiveSheet(); //データを書き込む sheet.getRange(1,1).setValue("1-1 あああ"); sheet.getRange(1,2).setValue("1-2 いいい"); sheet.getRange(2,1).setValue("2-1 かかか"); sheet.getRange(2,2).setValue("2-2 ききき"); }

  • データの追加

    function myFunction() { //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample01").getActiveSheet(); //データを追加 sheet.getRange(sheet.getLastRow()+1,1).setValue("追加データ"); }

  • JSON文字列として出力

    function doGet(e) { //スプレッドシートの取得 var sheet = openSheetFile("/SheetTest/Sample01").getActiveSheet(); //全てのデータを抽出 var datas = sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).getValues(); //JSON文字列に変換 var j = JSON.stringify(datas); //データを戻す return ContentService.createTextOutput(j); }

  • 操作用ファンクション

    Sheet.gs//ファイルの移動 //folder 移動先のフォルダインスタンス //fileId 移動するファイルのID function moveFile(folder,fileId){ //スプレッドシートをDrive操作用インスタンスに変換 var file = DriveApp.getFileById(fileId); if(folder != DriveApp){ //フォルダ移動 folder.addFile(file); DriveApp.removeFile(file); } } //フォルダーが存在するか確認 function getFolder(name){ //フォルダ名を分解 var bar = name.split("/"); //フォルダの階層を辿る var folder = DriveApp.getRootFolder(); for(var i=0;i < bar.length-1;i++){ var name = bar[i]; if(name){ var it = folder.getFoldersByName(name); var next = null; //フォルダの存在確認 if(it.hasNext()){ next = it.next(); if(next.isTrashed()) next = null; } if(!next){ //無ければ作る folder = folder.createFolder(name); if(!folder) break; } else folder = next; } } return folder; } function getFileName(path){ var bar = path.split("/"); return bar[bar.length-1]; } //ファイルのIDを返す //name ファイル名 function getFile(nam

  • 最初のステップ

    スクリプトの作成 プロジェクト名の設定 コードの入力 実行方法

  • データ追加テスト

    function test(){ addMessage("名前","メッセージ"); }

  • AndroidStudioでテストプログラムの作成

    AndroidStudioから新規プロジェクトで「AddNoActivity」を選択。ソースコードはパッケージ名(test)のExamleUnitTest.javaを使用します。

  • データ追加処理

    function addMessage(name,msg){ //スプレッドシートの取得 var sheet = openSheetFile(SHEET_NAME).getActiveSheet(); //追加行+1の取得 var lastIndex = sheet.getLastRow()+1; //IDの取得 var id = getId("ID"); //日付の取得 var date = new Date(); //データを追加 //setValuesは二次元配列を利用する為、[[データ,データ],[データ,データ]]のような記述になる sheet.getRange(lastIndex,1,1,4).setValues([[id,date,name,msg]]); }

  • 両面開発で気を付けるべきこと

    開発環境の設定 出来ることの違い

  • Node.jsとTypeScriptによるプログラミング入門

    Node.jsはサーバサイドのプログラミングをJavaScriptで行うためのフレームワークです。このフレームワークの特徴はランタイムライブラリが非同期を前提に作られていることです。そのため、直列に逐次実行していくプログラミング言語にをやってきたプログラマにとって、慣れるまでは不便や回りくどさを感じることになります。逆にプログラミングを全くやったことのない人間がNode.jsに手を出すのは無謀としか言い様がないので、他の言語を選択することをおすすめします。 Node.jsの特徴である非同期のメリットは、周辺へのデータアクセスが効率的になること、デメリットはプログラムが複雑化しやすいことです。複雑といっても大規模な範囲が複雑化するわけでは無く、個々の部分の記述量が増えるというだけなので、それほど致命的な問題にはなり得ません。 また、Node.jsはシングルスレッドを前提としており、マルチCPU環境での性能を出せないと言われることが多いですが、これはプロセスを複数立ち上げれば解決します。他のスクリプト言語でマルチスレッドに対応しているものもありますが、結局のところインタプリタ上でリソース共有のためのロックがかかってしまい、性能が発揮できない結果になります。ということでスクリプト言語系は、マルチCPUはマルチプロセスを使うことになります。 性能的を重視するのであればスクリプト言語はやめて、C/C++、golang、Java辺りを使いましょう。TypeScriptに関して

  • TypeScriptによる両面開発の利点

    ・同じ文法なので効率が上がる 例えばバックエンドをPHP、フロントエンドをJavaScriptで開発したケースです。この二つの言語、文法が似ています。似ているが故に同時開発すると、拡張for文などでミスります。PHPでfor-inを使おうとしてしまったりと、一瞬で気が付くミスですが、けっこうやってしまいがちです。完全に同じ文法の言語を使えば、こういった部分でのストレスがありません。・ソースコードが使いまわせる フロントエンドとバックエンドで同じような処理を書く場合があります。言語が違えばいちいち書き直しですが、同じ言語ならコピペで終了です。共通ライブラリとして整備しておけば、コピペの必要すらありません。 ・データのやり取りが楽 TypeScriptなら型が組めるわけですが、同じ言語ならこの型が共通化できます。特に威力を発揮するのは通信部分です。バックエンドとフロントエンドの通信は、Ajaxを用いた非同期通信を用います。やりとりの標準的な方法では、いったんJSON形式を通してパースし、お互いの終端でデコードして使います。TypeScriptなら、このデコード後の型が共通化できるのです。これが出来るか否かで、開発効率がまったく変わってきます。感覚的にはローカルファンクションを呼び出す感覚で通信が可能となるのです。

  • AndroidのGUIプログラム

    GAS側 Android側の準備 Androidのマニフェストの変更 MainActivity.javaの編集 結果をTextViewに表示する 通信機能の分離

  • if文

    function myFunction() { //Math.random()は小数型で0以上1未満の値を返す //その結果に数を掛けて整数にすると0~数-1になる。 var data = parseInt(Math.random() * 4); //0~3が返る if(data == 0) Logger.log("1 ああああ"); else if(data == 1) Logger.log("2 いいいい"); else Logger.log("3 うううう"); } 今回変数はvar宣言してます。varを使うと、function内でのみ使用可能な変数となります。

  • ログ出力と結果の確認

    ログ出力 ログとフォーマット ループによる出力 if文

  • ループによる出力

    function myFunction() { for(i=0;i<10;i++) Logger.log("%s番目",i); } 基本文法は一般のJavaScriptと同じです。変数は宣言しなくとも利用可能ですが、グローバル変数になります。

  • Java側

    class SendData{ public String msg; } class RecvData{ public int ret; public String[][] values; } public class ExampleUnitTest { final String GAS_ADR = "GASのアドレス"; @Test public void sendData(){ SendData sendData = new SendData(); sendData.msg = "送信テスト"; RecvData recvData = Json.send(GAS_ADR,sendData,RecvData.class); if(recvData != null && recvData.ret == 1) System.out.println("送信完了"); else System.out.println("送信エラー"); } //@Test public void recvData(){ RecvData recvData = Json.send(GAS_ADR,null,RecvData.class); if(recvData != null && recvData.ret == 1){ for(String[] value : recvData.values){ System.out.println(value[0]); //フィールド数が1でも受け取るときは配列になる } } else System.out.println("送信エラー"); } }

  • ログとフォーマット

    function myFunction() { Logger.log("%s+%s=%s",10,20,10+20); } 他の言語だと%sは文字列を表しますが、GASのLOG出力は全て%sを使用します。また、書式指定は出来ません。

  • スプレッドシートの操作

    GASを扱う場合、SpreadSheetをDBのかわりに活用すると効率的です。 ここではSpreadSheetを簡単に扱うためのコードを紹介します。操作用ファンクション スプレッドシートの操作 データの追加 JSON文字列として出力

  • ログ出力

    function myFunction() { Logger.log("あああああ"); } ログの表示は実行後にCTRL+Enterを押します。 実行時にいったん内容がクリアされるので、表示されるのは最後に実行した結果になります。

  • TypeScriptによる簡単フロントエンド開発(非モジュールバンドラ版)

    フロントエンド開発にTypeScriptを用いようと思っても、最初に何をすれば良いのか分かり辛いため、意外に高いハードルがあるのが現状です。 開発であらゆる便利機能を利用し、フル装備の環境を作るならWebPackのようなモジュールバンドラを使用することになりますが、設定内容や必要とするプラグインの情報量が多すぎて、最初からそれをやると大量の死人を出すことになります。 ここではJavaScriptからTypeScriptに移行する過程で、余計な機能などを一切入れず、コンパイラのみで行う最低限の設定内容を紹介します。

  • src/main.ts

    addEventListener("DOMContentLoaded", () => { const element = document.createElement('div'); element.innerText = "こんにちは世界"; document.body.appendChild(element); });

  • 実行方法

    公開 → ウエブアプリケーションとして導入 → 新しいバージョンを保存(新規以外の場合) → 導入これでサーバ上に作ったプログラムがデプロイされます。公開アドレスは以下の二種類があるので、必要に応じて使い分けてください。・公開用のアドレス(バージョンを切り替えないと更新されない)現在のウェブ アプリケーションの URL:・テスト用のアドレス(保存した時点で更新される)最新のコードのリンクをクリック

  • コードの入力

    function doGet() { var htmlData = "<h1>テストプログラム</h1>"; return HtmlService.createHtmlOutput(htmlData); }

  • dist/index.html

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" /> <script type="text/javascript" src="main.js"></script> </head> <body> </body> </html>

  • フロントエンド開発に関して

    前置きがいらない人は、このページは読み飛ばしてください。 TypeScriptによるフロントエンド開発は、素のJavaScript開発に比べ、その開発効率を飛躍的に上げることが可能です。・型チェックによる不正な代入の防止・開発環境と連携した入力補完によるメソッドやプロパティ、パラメータの明確化・最新の文法の対応と古い規格へのトランスコンパイル機能 一般的にTypeScriptはJavaScriptに型が加わった言語だという認識をされることが多いですが、実はそれだけに止まりません。型の定義を専用の定義ファイルに吐き出しておくことで、それを配ればオリジナルのファンクションやインタフェイスの名前やパラメータをチェックすることが出来ます。 例えばフロントエンド開発ではイベントの種類が多すぎて、全パラメータを覚えている人はいないであろうと思われるaddEventListener、これも型定義が用意されています。イベントの名前が網羅され、コールバック用の引数の内容まで開発時に表示されます。間違った使い方をすれば当然のごとくきっちりエラーが出ます。 document.createElementも、そに書いたDOMの種類が型として認識されます。//elementが自動的にHTMLDivElementとなるconst element = document.createElement('div'); これによって、作成したDOMのインスタンスに対して、不正な入出力が出来なくなります。もし追加プロパティなどのカスタマイズが必要な場合は、きっちり書かなければいけないところが逆に面倒ですが、それ以上にメリットが大きいのです。//divにcustomParamという追加プロパティを設定 const element = document.createElement('div') as HTMLDivElement&{customParam?:string}; そしてJavaScript自体もどんどん新しい文法が作られ、どんどん便利な文法が実装されていくのですが、古いブラウザでは対応できないという問題が発生します。特にループやイテレータ系など、使えばコードが簡潔に書けるようなものに関しては、本来ならどんどん使っていきたいところです。しかしそれをやった時点で、ある程度のクライアント環境を切り捨てなければなりません。 TypeScriptなら最新

  • プロジェクト名の設定

    初期状態で「無題のプロジェクト」になっているので、名前を変更します。これがGoogleDrive上でのファイル名となるので見失わないようにしてください。

  • 利点は大きいが移行するまでの壁も大きい

    TypeScriptによる両面開発は数々のメリットがある反面、壁が大きいのも確かです。まずNode.jsの非同期処理に慣れるまでそれなりに時間がかかります。これは素のJavaScriptでも同じですが、他の言語には無い特徴故に慣れるまでに時間を要します。さらにTypeScriptの型の扱いも、ケースごとにどう対処するのかという知識を蓄積するまでに、多少の時間をとられます。この壁を乗り越えた先にたどり着けるかどうかは、各々のやり方次第です。しかしWeb開発という面に限って言えば、とんでもなく大きな効率化を図ることが出来るのです。

  • 言語の選択

    Web開発を一つの言語で行おうと思った場合、事実上の選択肢は素のJavaScriptを使うか、AltScript系を使うことになります。 前者のJavaScriptは気軽にコーディングできる反面、気付かぬうちに危険なコードが混入します。仕様をきっちり把握していればある程度回避できますが、実は地雷原をサンダルで散歩するに等しい言語なのです。今日は無事でも、明日は足が吹っ飛ばされるかもしれません。 JavaScriptの危険性を回避するにはAltScript、中でも急速に伸びているTypeScriptを強くお勧めします。TypeScriptが一つ使えれば、フロントエンドとバックエンド両方が同じ言語で、しかもある程度の安全を担保した状態で開発出来るのです。

  • TypeScriptによるバックエンドとフロントエンドの両面開発

    言語の選択 TypeScriptによる両面開発の利点 両面開発で気を付けるべきこと 最終的な開発環境とビルド手順 利点は大きいが移行するまでの壁も大きい

  • 確認

    dist/index.html をブラウザで開いてください。ブラウザにこんにちは世界と表示されていれば成功です。

  • 開発準備とサンプルプログラムの実行

    パッケージの準備 ディレクトリとファイルの準備 tsconfig.jsonによるコンパイラの設定 コンパイル 確認

  • 開発環境の設定

    VSCodeなどの開発環境は、TypeScriptの文法チェックをするときにtsconfig.jsonを参照します。この設定値を元にチェック項目を判断するわけです。当然ですがバックエンドとフロントエンドでこの設定値が異なります。特に入出力ディレクトリは確実に異なった設定になるので、きっちり区別をつけておかないと、大量のエラーに悩まされることになります。 まず最初にやらないといけないのは、プロジェクトルートのディレクトリに配置するtsconfig.jsonです。tsconfig.json{ "exclude": [ "." ] } これを置いておかないと、全てのディレクトリの**.ts**が混合でチェックされてしまうので悲惨なことになります。これを配置したら、あとはフロントエンド用とバックエンド用のディレクトリそれぞれに**tsconfig.json**を作ればOKです。コンパイル時、手動でそれぞれコンパイルするならtsc -b configファイルのパス とします。 また、異なるtsconfig.jsonをトップのtsconfig.jsonから呼び出すこともできます。tsconfig.json{ "references": [ { "path": "フロントエンドパス" },{ "path": "バックエンドパス" } ], "exclude": [ "." ] } としておけば、tsc -b だけで、両方同時にビルドすることができます。ただし、フロントエンドはWebPackなどのモジュールバンドラを使うケースが多いのでその場合、ここに記述するのはバックエンドの参照のみになります。また、参照を受け付ける場合は、参照先の設定にtsconfig.json{ "compilerOptions": { "composite": true } } を入れておく必要があります。

  • スクリプトの作成

    GoogleDrive上で、新規「GoogleAppsスクリプト」を選びますメニューにない場合はアプリの追加から「GoogleAppsスクリプト」を選択してください。

  • 出来ることの違い

    バックエンドはファイルの入出力やDBアクセスなど、一通り何でもできます。ただしDOM操作などは標準対応しておらず、自分で組むか、jsdomのようなパッケージをnpmからとってくる必要があります。 フロントエンドはDOM操作が標準でできますが、当然ファイル操作などは出来ません。ブラウザ内で許可されているlocalstrageを使ったり、バックエンドに入出力要求する必要があります。 ということで使用可能なAPIはまったく異なるので、ここだけはきちんと区別して開発しなければなりません。

  • パッケージの準備

    適当な場所にディレクトリを作って開発環境を開きます。VSCodeがオススメです。ターミナルを開いたら、以下のコマンドを入力します。npm -y init npm i typescript npx tsc -initここまでで、TypeScriptのコンパイラとコンパイル方法を定義するためのtsconfig.jsonが生成されます。ちなみにnpmのグローバルインストールは一切しないでやっていくので、TypeScriptのコンパイラtscにはプロジェクト上のコマンドを示すnpxが頭に付きます。

  • ディレクトリとファイルの準備

    以下のような形でディレクトリとファイルを準備します/ (基本ディレクトリ) - dist index.html - src main.tsdist/index.html src/main.ts

  • バックエンドでTypeScriptを利用するための環境構築

    Node.js自体のインストールに関しては、サーバ構築系のCentOSとUbuntuの項目を参照してください。Windowsに関してはこのサイトで解説しなくても、VSCodeとNode.jsのインストールプログラムを実行するだけなので問題ないと思われます。TypeScriptのインストール

  • Test03.html

    <!DOCTYPE html><html><head><meta charset="UTF-8" /><title>JavaScriptTest</title><script type="text/javascript">(function(){//イベント設定addEventListener("mouseup", mouseUp,false);addEventListener("touchend", mouseUp,{passive: false});addEventListener("mousemove", mouseMove, false);addEventListener("touchmove", mouseMove,{passive: false});//ウインドウ制御用グローバルオブジェクトWIN = { moveNode: null, frame: null};//マウスとタッチイベントの座標取得処理function getPos(e){ var p = {}; if (e.targetTouches && e.targetTouches.length) { var touch = e.targetTouches[0]; p.x = touch.pageX; p.y = touch.pageY; } else { p.x = e.x; p.y = e.y; } return p;}//マウスが離された場合に選択をリセットfunction mouseUp(e){ WIN.moveNode = null; WIN.frame = null;}function mouseMove(e){ if(WIN.moveNode){ var p = getPos(e); //座標の取得 var node = WIN.moveNode; //移動中ノード var x = node.getPosX(); var y = node.getPosY(); var width = node.getWidth(); v

  • フレームウインドウと重ね合わせ処理

    フレームウインドウを表示するサンプルだ。ウインドウの移動の他に、フレームを引っ張ってサイズを変更する部分も含め、重ね合わせも順位の変更も行っている。 今回はタブレットやスマートフォンのタッチパネルのイベントも含んでいる。マウスのイベントとは座標の取り方が違うので注意が必要だ。 極力ソースコードの量を削るため頑張ったものの、それなりのコード量になってしまった。出力結果 Test03.html

  • Test02.html

    <!DOCTYPE html><html><head><meta charset="UTF-8" /><title>JavaScriptTest</title><script type="text/javascript">(function(){addEventListener("mouseup", mouseUp);addEventListener("mousemove", mouseMove);WIN = {moveNode:null};function mouseUp(e){ WIN.moveNode = null;}function mouseMove(e){ if(WIN.moveNode){ var node = WIN.moveNode; node.setPos(e.x + WIN.x,e.y+WIN.y); if(e.preventDefault) e.preventDefault();else e.returnValue=false; }}WIN.createWindow = function() { //ウインドウ用ノードの作成 var node = document.createElement('DIV'); //位置を絶対位置指定 node.style.position = 'fixed'; //境界の区別用に背景色の設定 node.style.backgroundColor = '#FFFF00'; //位置指定メソッド node.setPos = function (x, y) { this.style.left = parseInt(x) + 'px'; this.style.top = parseInt(y) + 'px'; } node.getPosX = function(){return parseInt(this.style.left);} node.getPosY = function () {return parseInt(this.style.top);} //サイズ指定メソッド node.setSize = functi

  • ウインドウのドラッグドロップ

    マウスのイベントを受け取って、ウインドウの移動処理を行う。マウスをクリックしたときに座標を記憶し、マウスの移動とともにウインドウの座標を変え、マウスが離されたら移動処理を解除する。この処理のため、移動ノードの情報を記憶する共通変数が必要となる。 クリックの処理はウインドウのノードで処理するが、移動と離された場合のイベントはブラウザのクライアント領域全体に対して行う。出力結果 Test02.html

  • Test01.html

    <!DOCTYPE html><html><head><meta charset="UTF-8" /><title>JavaScriptTest</title><script type="text/javascript">(function(){WIN={};WIN.createWindow = function() { //ウインドウ用ノードの作成 var node = document.createElement('DIV'); //位置を絶対位置指定 node.style.position = 'fixed'; //境界の区別用に背景色の設定 node.style.backgroundColor = '#FFFF00'; //位置指定メソッド node.setPos = function (x, y) { this.style.left = parseInt(x) + 'px'; this.style.top = parseInt(y) + 'px'; } //サイズ指定メソッド node.setSize = function (width, height) { this.style.width = parseInt(width) + 'px'; this.style.height = parseInt(height) + 'px'; } //ノードを本文へ追加 document.body.appendChild(node); //ノードを戻す return node;}})();addEventListener("DOMContentLoaded", Main);function Main() { //ウインドウの作成 var win = WIN.createWindow(); win.setSize(200, 100); win.setPos(32, 64); win.textContent = "ウインドウテスト"; var win2 = WIN.createWindow(); win2.setSize(100, 200);

  • JavaScriptによるウインドウシステムの作成

    サーバやプログラミングの技術情報

  • プッシュ、プル、フェッチ

    プッシュ ブランチをリモートに送信するプル ブランチをリモートから受け取るフェッチ コードの送受信は行わず、ツリーの関係情報を更新する

  • リモートリポジトリ

    GitHub上にリポジトリの作成 SourceTreeからリモートの設定 ブランチをプッシュ プッシュ、プル、フェッチ

  • ブランチをプッシュ

    リボンのプッシュボタンを押すブランチを全て選択しプッシュボタンを押すユーザ認証を求められたら、入力するブランチがプッシュできたかどうか、GitHubのサイトを更新して確認する

  • SourceTreeからリモートの設定

    メニューの「リポジトリ」から「リポジトリ設定」を選ぶデフォルトリモートにチェックURL/パスにクリップボードの内容を貼り付けOKを二回これでリモートリポジトリの設定は完了

  • ブランチの追加と枝分かれ

    Test.javapublic class Test { public static void main(String[] args) { System.out.println("Gitテスト"); System.out.println("枝分かれ"); }}コミット SourceTreeでコミットを行うとHEADという一時ブランチが生成される このままだとブランチを移動した際に消えてしまうので、新規でブランチを作成する必要があるブランチの追加 リボンのブランチを押して名前を付けてブランチを作成 これでリポジトリ内に複数のブランチが生成される ブランチはダブルクリックで自由に移動できる ・注意点 カレントブランチをしっかり把握しておくこと カレントブランチはSourceTree上で太字表示されている 間違ったブランチでソースコードを修正しないように気をつける

  • 追加コミットとソースの巻き戻し

    Test.javapublic class Test { public static void main(String[] args) { System.out.println("Gitテスト"); System.out.println("追加"); }}以上のように、内容を追加する。コミット SourceTree側でStageAllをしてから、先ほどと同じ手順でコミットを行う以前のコミットに移動 樹形図の最初のコミットをダブルクリック クリーンにチェックを入れてOKを押す ソースコードが戻ったか確認

  • SourceTree

    SourceTreeの利用には無料のユーザ登録が必要となるので、必要な情報を登録すること初回起動時・Mercurialは使用しない・Gitが入っていない環境だとダウンロードを求められるのでダウンロード・次にSSHキーの読み込み → 使わないのでNo・GitHubやBitbacketの設定はスキップ

  • アプリケーション

    SourceTree

  • Webサービス

    GitHub Bitbucket

  • Gitを扱うためのソフト(Windows)

    ・Git for Windowshttps://git-for-windows.github.io/Windows上でGitを扱うためのソフト主にUnix系と互換性のあるコマンドラインツールが含まれているSourceTreeがあれば、こちらはインストールしなくても問題は無い・SourceTreehttps://ja.atlassian.com/software/sourcetreeGitをGUIで操作するためのアプリケーションこれを使えばGitのコマンドを覚えなくても、おおよその操作が可能ただし込み入った操作を行う場合は、Gitコマンドを扱う必要がある

  • Z-index

    Test05.html<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>CSSTest</title> <style type="text/css"> body>div { width: 100px; height: 100px; position: absolute; } body>div:nth-child(1){ left: 10px; top: 20px; z-index: 1; background-color: red; } body>div:nth-child(2){ left: 60px; top: 20px; z-index: 4; background-color: green; } body>div:nth-child(3){ left: 10px; top: 80px; z-index: 3; background-color: blue; } body>div:nth-child(4){ left: 60px; top: 80px; z-index: 2; background-color: gray; } </style></head><body> <div>コンテンツ</div> <div>コンテンツ2</div> <div>コンテンツ3</div> <div>コンテンツ4</div&

  • Box-sizing

    Test04.php<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>CSSTest</title> <style type="text/css"> body>div { width: 250px; background-color: red; overflow: visible; } body>div>div { margin: 30px; padding: 30px; background-color: blue; height: 100px; } body>div>div>div { background-color: yellow; } body>div:nth-child(2)>div{ box-sizing: border-box; } </style></head><body> <div> <div> <div>コンテンツ</div> </div> </div> <div> <div> <div>コンテンツ2</div> </div> </div></body></html>表示結果content-box 指定したサイズに対して、さらにpaddingやborderのサイズを上乗せborder-box 指定したサイズの中にpaddingやborderを含めるJavaScriptで厳密に位置を調整したい場合はborder-boxを指定することが多いただし

  • Position

    Test03.html<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>CSSTest</title> <style type="text/css"> div { opacity: 0.7; } div:nth-child(1),div:nth-child(5) { background-color: red; position: static; width: 200px; height: 50px; left: 50px; top: 20px; } div:nth-child(2) { background-color: green; position: relative; width: 200px; height: 50px; left: 50px; top: 20px; } div:nth-child(3) { background-color: blue; position: absolute; width: 200px; height: 50px; left: 50px; top: 20px; } div:nth-child(4) { background-color: gray; position: fixed; width: 200px; height: 50px; left: 50px; top: 20px; } </style>&l

  • MarginとPadding

    Test02.html<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>CSSTest</title> <style type="text/css"> body { margin: 0; padding: 0; } body>div { width: 200px; background-color: red; overflow: visible; } body>div>div { margin: 30px; padding: 10px; background-color: blue; } body>div>div>div { background-color: yellow; } </style></head><body> <div> <div><div>コンテンツ</div></div> </div></body></html>表示結果 MarginとPaddingなんて今更と思う人も多いだろう。だが、話はそう単純ではない。まず誰もが知っているであろう基本を書いてみるmargin 隣接ノードとの距離padding 子ノード配置空間 そしてこの出力結果である。赤い部分がマージンで、青い部分がパディングを適用した結果だ。 本来であれば赤い部分は上下にも表示されるはずだが、隣接ノードが存在しないと上下に関しては適用されない。ここまでは一般的なサイトであれば解説されている話だ。ではなぜ適用されないのだろう?いや、そもそも本当に適用されていないのか? 実はきっちり上下のマージンが適用されている。どこにかって?それは白い部分だ。マージンがはみ出している

  • 初回コミットとブランチの作成

    作業ツリーファイルに表示されているもののうち、いらないものを無視するbin/Test.class (binフォルダを無視).settings/* (場合に応じて、今回はそのままでもOK).gitignoreファイルが作成され、無視が設定できたら Stage Allを押し、対象ファイルをステージにセットリボンのコミットを押して、下部のテキストボックスに何を更新したのか分かるようにメッセージを書き込むコミットボタンを押すと自動的にmasterブランチが作成される

  • リポジトリの作成

    新規/クローンを作成するリポジトリの作成タブ保存先のパスでプロジェクトのフォルダを選択(ワークスペースの階層を指定しないこと)作成ボタンを押す

  • SouceTreeの操作

    リポジトリの作成 初回コミットとブランチの作成

  • Display

    Test01.html<!DOCTYPE html><html><head> <meta charset="UTF-8" /> <title>CSSTest</title> <style type="text/css"> div { background-color: lightslategrey; margin: 1px; padding: 1px; } div:nth-child(1) { display: block; width: 200px; height: 50px; } div:nth-child(2) { display: inline; width: 200px; height: 50px; } div:nth-child(3) { display: inline-block; width: 200px; height: 50px; } </style></head><body> <div>block</div> <div>inline</div> <div>inline-block</div></body></html>表示結果まず基本中の基本はdisplayによる表示形式の指定だblock 強制改行が入るinline サイズの指定が出来ない inline-block サイズの指定が可能で改行は入らない DIVタグはblockがデフォルトで、相対してよく使われるSPANタグはinlineだ。表示形式の性質は、何をやるにしても基本中の基本の知識となる。

  • リポジトリの作成

    Javaのプログラムを使って、チュートリアル的に利用の仕方を確認するJavaのコードを入力 SouceTreeの操作 追加コミットとソースの巻き戻し ブランチの追加と枝分かれ

  • セレクター

    CSSを扱い場合、タグに直書きすることは少ない。シートを別に作ることが一般的だが、そこで使われるのはセレクターだ。一般的にはtag、class、idを用いて対象を指定する。しかし今回はclassとidを排除して記事を作成する。理由は、セレクターにはclassとidを使用するという固定観念を排除するためだ。 まともな記事は、もっとまともな人の記事を参照して欲しい。

  • Bitbucket

    GitHubと同様に、無料でリモートリポジトリを提供しているサービス。https://bitbucket.org/

  • タグに関して

    まず大前提として、CSSを使うならタグを使い分ける必要は無いと言うことだ。ほとんどの場合、タグはDIVだけで用が足りる。それどころか、逆にタグを使い分けることは避けた方が良い。なぜなら各種タグの表示結果は、ブラウザによって異なるからだ。 以上の理由からこの解説記事においては、9割方DIVタグしか出てこない。

  • GitHub

    Gitのリモートリポジトリを無料で作成できるサービスを提供している。利用するにはユーザー登録が必要。ただし他人のリポジトリを受け取るだけなら、ユーザ登録がなくても問題は無い。https://github.com/ログイン時にパスワードを複数回間違えると、同一IPのログインが一律にブロックされるので、入力ミスに気をつけること。講座とかで一斉にアカウントを作るような内容をやるときに、ちょっとアレな人が多いときに困る。

  • 制御構文

    if 文字列@echo offset a=ABCDif %a%==abcd (echo 正解) else (echo 不正解)pause@echo offset a=ABCDif /i %a%==abcd (echo 正解) else (echo 不正解)pause@echo offset a=ABCDif not %a% == ABCD (echo 不正解) else (echo 正解)pause== 等しいEQU 等しいNEQ 等しくないLSS より小さいLEQ 以下GTR より大きいGEQ 以上if ファイル@echo offif exist out.txt (echo ファイル有り) else (echo ファイル無し)pause@echo offif not exist out.txt (echo ファイル無し) else (echo ファイル有り)pausefor@echo offfor /l %%i in (5,1,20) do echo %%ipause@echo offfor /l %%i in (5,1,20) do if %%i lss 10 (echo 0%%i) else (echo %%i)pausecall@echo offcall :func 0 10call :func 30 40:func for /l %%i in (%1,1,%2) do if %%i lss 10 (echo 0%%i) else (echo %%i) pause

  • 基本的な入出力

    ・メッセージの出力echo テスト・キーが押されるまで待機echo テストpause・コマンドの非表示行頭に@を付けることによって、コマンドがエコーバックされなくなる @echo テスト@pause・コマンドの非表示2 echo offによって、それ以降のコマンドがエコーバックされなくなる一般的なバッチファイルはほぼこのコマンドから開始される@echo offecho テストpause・変数値を設定するのはset、取り出すときは%で囲む @echo offset data1=あいうえおset data2=かきくけこecho %data1% %data2%pause・改行echo一つごとに自動的に改行される @echo offset data1=あいうえおset data2=かきくけこecho %data1%echo %data2%pause・改行して命令を続ける ^によって、命令を複数行にまたがって記述できる@echo offset data1=あいうえおset data2=かきくけこecho %data1%^%data2% pauseリダイレクト(新規) 標準出力された文字列を新規ファイルに書き込むことが出来る@echo offecho リダイレクト >out.txtpauseリダイレクト(追加) >>によって、ファイルへ追加する形で書き込むことが出来る@echo offecho リダイレクト >>out.txtpauseリダイレクト(コンソール指定) 標準出力のデフォルトはコンソールであるつまり指定することに意味は無い@echo offecho あいうえお >conpauseコメント remを付けることによって、その行は実行されなくなる@echo offrem コメント行pauseキーボード入力 代入しているものが表示され、入力した文字列が変数に代入される意味が分からないと思うが、実行して結果を確認して欲しい@echo offset /p data="キーボード入力"echo 入力されたデータは%data%pause

  • BATファイルの作成

    ・GUI環境の場合 1 ファイルエクスプローラの設定で、登録されている拡張子は表示しないのチェックを外す 2 テキストファイルを作成し、拡張子をbatにする・コマンドプロンプトの場合 1 対象フォルダに移動 2 notepad ファイル名.bat

  • 公式リファレンス

    MicrosoftからPDFファイルで提供されている利便性を考えればリファレンスをWEBサイト上でHTMLとして提供してもらいたいところではあるが、無いよりはましであるhttps://www.microsoft.com/en-us/download/details.aspx?id=56846

  • 参照型とObject

    Object型はあらゆるクラスの大本の親となるため、どの参照型でも代入できる。//Object型で変数を定義Object a = 10; //自動的にInteger型 Object b = "あいうえお"; //自動的にString型//内容を出力System.out.println(a);System.out.println(b);//各インスタンスのクラス名を表示System.out.println(a.getClass().getName());System.out.println(b.getClass().getName());各クラスの操作を行う場合は、キャストを行いクラスを明確にする必要がある。//Object型で変数を定義Object a = 10; //自動的にInteger型 Object b = "あいうえお"; //自動的にString型//内容を出力System.out.println((Integer)a+(String)b);

  • 基本コード

    両方とも同じように使えるint a = 10;Integer b = 20;System.out.println(a+b);参照型はメソッド(命令)が使えるint a = 10;Integer b = 20;System.out.println(a+b.toString());インスタンスを明示的に作成Integer a = new Integer(10);Integer b = new Integer(20);System.out.println(a+b);比較intの場合int a = 10;int b = 10;if(a == b) System.out.println("同じ値");else System.out.println("違う値");比較Integerの場合、アドレスを比較するInteger a = new Integer(10);Integer b = new Integer(10);if(a == b) System.out.println("同じ値");else System.out.println("違う値");参照型の比較方法、値を比較するInteger a = new Integer(10);Integer b = new Integer(10);if(a.equals(b)) System.out.println("同じ値");else System.out.println("違う値");

  • 種類と構造

    プリミティブ型 参照型int Integerfloat Floatdouble Doubleboolean Booleanchar Char String 配列 その他クラスプリミティブ型はアクセスが速く消費メモリが少ないそのかわり単純なデータの記憶しか出来ない参照型はアクセスにワンクッション必要で、アドレスなどの付加情報が必要で消費メモリが増える メソッドなど追加機能を含めることが出来るObjectが基本クラスとなり、データ型の情報などを取得することも出来る

  • if文 ブロック

    if文の処理をブロック{}で囲った場合、条件が真だとブロックの内容が実行される。if文は{}のブロックを一命令と認識する。ブロックは命令をグループ化するものなので、ifとは無関係に使用することができる。int a = 5;if(a!=5){ a = a * 2; a = a * 2;}a = a * 2;

  • if文

    if文は条件によって処理を分岐させるのに利用する。条件が真(合っていた場合)だと次の命令を[一つだけ]実行し、偽(間違っていた場合)は次の命令をスキップする。また、Javaでは代入(=)と区別するため、等価比較(==)の記号を利用する。int a = 5;int b = 0;if(a == 1) b = 1; //セミコロンまでを一命令と数えるif(a == 5) b = 2;if(a == 10) b = 3;

arrow_drop_down

ブログリーダー」を活用して、空雲さんをフォローしませんか?

ハンドル名
空雲さん
ブログタイトル
空雲リファレンス
フォロー
空雲リファレンス

にほんブログ村 カテゴリー一覧

商用