SQLの窓

2020年03月28日


Google Classroom は無料の G Suite for Education アカウントが必要

個人アカウントで作ろうとしたら怒られたというお話



作成は本来 Google Apps Script の拡張 API から行いますが、こちらの Try this API で簡単に実行できます



結局使え無いんですが、きっちりフォルダは作られてしまうので削除が必要です




で、どうもコースの実体は残っているようなんですが、アーカイブできないので削除もできないというか...
一般アカウントでやる事では無いという結論です



posted by lightbox at 2020-03-28 15:45 | Google | このブログの読者になる | 更新情報をチェックする

2020年03月25日


教室と一対一のフォルダより新しく登録されたフォルダの中にあるZoom動画ファイルを該当するClassroom の コース内の該当するトピックに登録する

起動はトリガで夜間バッチです。

▼ 時間割テーブル


// *******************************************
// 教室と一対一のフォルダより新しく登録された
// フォルダの中にあるZoom動画ファイルを該当する
// Classroom の コース内の該当するトピック
// に登録する
// *******************************************
function myFunction() {

	// 教室用のフォルダ / 共有ドライブ に作成済
	// ( id は、表示されている URL より取得 )
	var folder = DriveApp.getFolderById("1o-C4Vn-2zBYn8ENOAvVwd3g8BNp9xS-E");
	var Iterator = folder.getFolders();

	// フォルダ内の一覧
	while (Iterator.hasNext()) {
		var folder = Iterator.next();

		// デバッグ用
		// GmailApp.sendEmail("メールアドレス", "Zoom 動画 フォルダ名", folder.getName());

		// 動画が格納されているフォルダ名( Zoom が自動作成したもの )
		var target = folder.getName();

		// Zoom フォルダ名より曜日番号を取得
		var youbiNum = getYoubi(target);

		var spreadsheet = SpreadsheetApp.getActive();

		var timeNum = getTime(spreadsheet, target);
		if (timeNum == -1) {
			continue;

		}

		var i = 1;
		var exist = false;

		while (true) {

			// 登録済のフォルダを排除する為に順に比較していく
			var targetRange = spreadsheet.getRange('A' + i);
			var cellWork = targetRange.getValue().toString();
			if (cellWork == '') {
				// 新規なので、スプレッドシートの A 列の最後に追加する
				targetRange.setValue(target);

				// MIME で絞ってファイル一覧を取得
				var files = folder.getFilesByType("video/mp4");
				// フォルダ内の動画ファイルをチェック
				while (files.hasNext()) {

					var file = files.next();

					// 拡張子 .mp4 のみを取得
					var work = file.getName();
					var exts = work.split(".");
					if (exts[1] != "mp4") {
						continue;

					}

					// Google ドライブ上の 動画の ID
					var fileId = file.getId();
					var courseId = getCourseId(spreadsheet, youbiNum, timeNum);
					// 本来は条件を元に決定する
					var topicId = getTopicId(spreadsheet, youbiNum, timeNum);

					// 課題作成用の JSON
					var json = {
						"materials": [
						{
							"driveFile": {
								"driveFile": {
									"id": fileId

								},
								"shareMode": "VIEW"

							}

						}
						],
						"description": "動画の補足説明",
						"assigneeMode": "ALL_STUDENTS",
						"state": "PUBLISHED",
						"title": target,
						"topicId": topicId,
						"workType": "ASSIGNMENT"

					};

					// デバッグ用
					// GmailApp.sendEmail("メールアドレス", "JSON", JSON.stringify(json));


					// 課題を投稿
					try {
						Classroom.Courses.CourseWork.create(json, courseId);

					}
					catch(e) {
						targetRange.setValue("");
						GmailApp.sendEmail("メールアドレス", "Classroom 投稿エラー", target);


					}

				}

				break;

			}
			else {
				if (cellWork == target) {
					exist = true;
					break;

				}
				else {
					i++;

				}

			}

		}


	}



}

// *******************************************
// Zoom フォルダ名より曜日番号を取得
// *******************************************
function getYoubi(folderName) {

	var ymdString = folderName.substr(0, 10);
	var dateData = new Date(ymdString);
	var youbiNum = dateData.getDay();

	return youbiNum;

}

// *******************************************
// Zoom フォルダ名より時間割テーブル上の
// 時限番号を取得
// *******************************************
function getTime(spreadsheet, folderName) {

	var timeNum = -1;

	var rangeData1 = [];
	var rangeData2 = [];

	// C 列にある時限の時間範囲を配列で取得
	for (var i = 1; i < 10; i++) {
		rangeData1.push(spreadsheet.getRange("C" + (4 + 4 * (i - 1))).getValue().toString());
		rangeData2.push(spreadsheet.getRange("C" + (5 + 4 * (i - 1))).getValue().toString());

	}

	//  var rangeData1 = ["09:20:00", "11:00:00", "13:30:00", "15:10:00"];
	//  var rangeData2 = ["10:59:00", "12:40:00", "15:09:00", "16:50:00"];

	// 対象の時刻部分を取得
	var ymdString = folderName.substr(0, 19);
	ymdString = ymdString.replace(/\./g, ":")
	var dateData = new Date(ymdString);

	// 範囲を持つ配列より時限を決定
	for (var i = 0; i < 9; i++) {
		if (rangeData1[i] != "") {
			var rangeWork1 = new Date(folderName.substr(0, 10) + " " + rangeData1[i]);
			var rangeWork2 = new Date(folderName.substr(0, 10) + " " + rangeData2[i]);
			if (rangeWork1 <= dateData && dateData <= rangeWork2) {
				timeNum = i + 1;

			}
		}
	}

	return timeNum;

}


// *******************************************
// 曜日と時限よりコースを取得
// *******************************************
function getCourseId(spreadsheet, youbiNum, timeNum) {

	var youbiRange = ["", "D", "E", "F", "G", "H", "I"]

	var targetRange = spreadsheet.getRange(youbiRange[youbiNum] + (2 + 4 * (timeNum - 1)));
	var courseId = targetRange.getValue().toString();

	return courseId;


}

// *******************************************
// 曜日と時限よりトピックを取得
// *******************************************
function getTopicId(spreadsheet, youbiNum, timeNum) {

	var youbiRange = ["", "D", "E", "F", "G", "H", "I"]

	var targetRange = spreadsheet.getRange(youbiRange[youbiNum] + (3 + 4 * (timeNum - 1)));
	var topicId = targetRange.getValue().toString();

	return topicId;


}

// *******************************************
// 作業用のコースID 一覧( 日本語名も ) を K・L
// 列に作成
// トピック一覧も N・O 列に作成
// *******************************************
function setCourseId() {

	var spreadsheet = SpreadsheetApp.getActive();

	var json = Classroom.Courses.list();

	var cnt = json.courses.length;

	for (var i = 0; i < cnt; i++) {
		var targetRange = spreadsheet.getRange('K' + (i + 1));
		targetRange.setValue(json.courses[i].id);
		targetRange = spreadsheet.getRange('L' + (i + 1));
		targetRange.setValue(json.courses[i].name);

	}

	var jsonTopic = null;

	var l = 0;
	for (var i = 0; i < cnt; i++) {
		jsonTopic = Classroom.Courses.Topics.list(json.courses[i].id);
		try {
			for (var j = 0; j < jsonTopic.topic.length; j++) {
				var targetRange = spreadsheet.getRange('N' + (l + 1));
				targetRange.setValue(jsonTopic.topic[j].topicId);
				targetRange = spreadsheet.getRange('O' + (l + 1));
				targetRange.setValue(jsonTopic.topic[j].name);
				l++;

			}

		}
		catch(e) {
		}


	}

}





posted by lightbox at 2020-03-25 23:02 | Google | このブログの読者になる | 更新情報をチェックする

2020年03月08日


Google Apps Script : 動画を添付して Classroom の指定のトピックへ課題として投稿する

関連する記事

Google Apps Script : 時間主導のトリガを使用して、CRON のように一定間隔でスクリプトを実行する


このコードは本来、時間主導のトリガを使用して、投稿していない動画があった場合に実行するものです。

( ✅注意 ) いろいろ調べましたが、『資料の作成』は、API からは実行できるようになっていませんでした。
function myFunction() {

	// https://any-api.com/googleapis_com/classroom/docs/courses/classroom_courses_courseWork_create

	// コースID は最初に取得しておいて、コース毎のトリガを作成する
	var courseId = "35126354603"  // クラス番号

	// スプレッドシートより、動画が保存されているフォルダIDを取得
	var spreadsheet = SpreadsheetApp.getActive();
	spreadsheet.getRange('A1').activate();
	var target = spreadsheet.getCurrentCell().getValue();

	var folder_id = target;  // 動画のあるフォルダID
	var target_folder = DriveApp.getFolderById(folder_id);

	var files = target_folder.getFilesByType("video/mp4"); // mp4 の一覧

	// フォルダ内の動画ファイルをチェック
	while( files.hasNext() ) {

		var file = files.next();
		// 本来はこのid が既に存在している場合は continue ( チェックは スプレッドシートを利用する )
		var fileId = file.getId();
		// 本来は条件を元に決定する
		var topicId = "53042801088";  // 課題A( スプレッドシートを利用する )

		// 課題作成用の JSON
		var json = {
			"courseId" : courseId,
			"materials": [
				{
					"driveFile": {
						"driveFile": {
							"id": fileId
						},
						"shareMode": "VIEW"
					}
				}
			],
			"description": "動画の補足説明",
			"assigneeMode": "ALL_STUDENTS",
			"state": "PUBLISHED",
			"title": "動画のタイトル",
			"topicId": topicId,
			"workType": "ASSIGNMENT"
		};

		// 課題を投稿
		Classroom.Courses.CourseWork.create(json, courseId);
	}
}




posted by lightbox at 2020-03-08 14:45 | Google | このブログの読者になる | 更新情報をチェックする

2020年03月07日


Google Apps Script : 時間主導のトリガを使用して、CRON のように一定間隔でスクリプトを実行する

関連する記事

Google Apps Script(GAS) で、Google Classroom に投稿する


一定間隔で、Classroom になんらかの授業用データを作成する為の準備用作業です。

▼ まず Google スプレッドシートを作成してスクリプトエディタを起動します


▼ コースid ( 整数文字列 ) と コース名をメールに送信するコードを保存


▼ スクリプト名を決定して保存


▼ スクリプトエディタのサービスの追加で、Classroom の API を使用可能にする


▼ トリガ登録画面を表示する


▼ トリガ登録


▼ トリガの時間間隔を決定


このスクリプトは、指定のメールアドレスに現在存在する コースid( 自分はクラス番号と呼んでます ) と名前を送っています。
function myFunction() {

	var response = Classroom.Courses.list();
	var courses = response.courses;
	var course = "";
	for (i = 0; i < courses.length; i++) {
		course = courses[i];
		var now = new Date();
		GmailApp.sendEmail("メールアドレス",
						"Classroom の id と名前",
						course.id + " : " + course.name + " : " +now.toString()
		);
	}

}




リファレンス



posted by lightbox at 2020-03-07 20:38 | GAS | このブログの読者になる | 更新情報をチェックする

2020年03月01日


JGREP 2.0.5 は Windows10 でも重宝しています

ダウンロードページ

要するに、あるキーワードが記述されたソースを、ドライブの中から拾い出すアプリケーションです。
( 例えばデータベースのテーブル名とか... )



設定ダイアログ

※ F10 で開く環境設定ダイアログです



このソフトは、機能の特性上検索後のテキストデータを表示する機能が必要になりますが、既存のエディタを使う事を想定しており、世の中にある有名なエディタのコマンドライン引数を簡単に設定できるようになっています。



このソフトを使うシチュエーションでは、同様の操作を続けて行う可能性がありますので、常に指定した検索設定は保存しておくほうが賢明です。

検索後、その行でエディタを開く



その他

★ 正規表現を記述する場合は、『正規表現をしない』チェックを外します
★ 大文字小文字を区別したい場合は、『大文字小文字を区別する』にチェックします




posted by lightbox at 2020-03-01 21:09 | フリーソフト | このブログの読者になる | 更新情報をチェックする

DF.exe ( テキストファイル差分表示 ) の初期基本設定

1) Terapad を外部エディタとして使用する

"インストールパス\TeraPad.exe" /j=%L "%P"



2) キャラクタセットの設定

Auto でうまくいかない時は固定で正しいキャラクタセットに変更します



DF ダウンロード( Vector )
Terapad ダウンロード( Vector )



中のウインドウ表示を空にして、比較したいファイルを順にウインドウへドラッグ&ドロップします(フォルダごと比較も可)


関連する記事

TeraPad 導入時の設定


このページの PDF



posted by lightbox at 2020-03-01 01:02 | フリーソフト | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり