SQLの窓

2023年02月02日


Google 共有ドライブの容量の上限について

ええと、上限が超えたと報告があって、対応する事となったのですが...
相変わらず Google のドキュメントは要点を取り出しにくい

結論から言うと、該当する共有ドライブを新しい組織に所属させて、組織単位で上限設定可能です。

1) マイドライブの上限は無いように思われる。
2) 共有ドライブの上限は、デフォルトでは 100G と書いてある。
3) しかし、対象の共有ドライブは 1テラ超えてからエラーが発生していた。
4) 全ての共有ドライブの上限を上げるわけにいかないので、個別の方法を調査。
5) どうも最近できた機能らしく、所属組織毎に共用ドライブを割り振れる。
6) そして、 所属組織毎に容量上限が設定できるので、新しい組織で上限を 10テラ に変更。

※ 所属組織は、デフォルトではルートですが、どの階層でもそこで上書きができます。 
Google Workspace for Education です
※ 一番上の一部を別の共有フォルダにある程度移動していて、これではあかんなぁ...となって調査


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

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年02月29日


Google Classroom のテーマ画像のサイズと既存画像をテーマ画像として使用してみた手順



1010 x 250 のようなので、それより大きな画像よりそのサイズで作成して利用してみたいと思います。

https://pixlr.com/x を使用して、既存の画像を縮小してトリミングしました



▼ しかし、結局再度トリミングする結果となりました


Classroom のテーマとして使用した状態






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

2019年01月03日


Google Chrome でスマホのソースコードをごく普通に表示して利用する

現状では、F12 でデベロッパーツールで device を トグルしてスマホ表示にしてからソースを表示しても、PC のソースしか表示されません。

なので、『view-source:』で表示している状態で F12 でベロッパーツールを表示して device を トグルします。



しかし、このままでは UI がスマホのエミュレータ状態でいろいろ利用しづらいので、再度 device をトグルとます。そうすると、スマホのソースコードでかつ画面いっぱいで利用できて、コピーペーストも可能な状態になります。






posted by lightbox at 2019-01-03 14:36 | Google | このブログの読者になる | 更新情報をチェックする
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 終わり