SQLの窓

2017年10月29日


TD 内のテキストを入力可能にする tableinput.js / jQuery プラグイン

テーブルの TD 要素の中がテキストのみの場合、tableinput.js プラグインで入力可能になります

オプションを省略したり、rowstart を省略すると、先頭の行を対象外にします。( rowstart の デフォルトは 1 )

tableinputEach によってテーブルの一覧を td のコレクション(jQuery のオブジェクト)単位で取得します

td.data("change") で、データが変更されたかどうかを取得できます
td.data("text") で最初のデータを取得できます

▼ 画像


▼ デモ実行
コード 氏名 フリガナ
0001 浦岡 友也 ウラオカ トモヤ
0002 山村 ひろよ ヤマムラ ヒロヨ
0003 多岡 冬行 タオカ フユユキ
0004 高田 冬美 タカタ フユミ
0005 内高 友之 ウチタカ トモユキ

上のデモのコード
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://lightbox.sakura.ne.jp/demo/template/lightbox-env/tableinput.js" charset="utf-8"></script>
<style>
.inputtd {
	text-decoration: underline;
	cursor: crosshair;
	background-color: pink;
}
.tableinput {
	font-family: Arial, Helvetica, Verdana, "ヒラギノ角ゴPro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", Meiryo, "MS Pゴシック", sans-serif;
	font-size: 16px;
}

#target_table {
	border-collapse: collapse;
	border: solid #c0c0c0 1px;
	background-color: #FFFFFF;
}
#target_table  th {
	padding: 10px;
	border: solid #808080 1px;
	background-color: silver;
}
#target_table td {
	padding: 10px;
	border: solid #c0c0c0 1px;
}
</style>
<input type="button" id="tableinput_action" value="実装">
<input type="button" id="tableinput_check" value="変更の確認" disabled>
<table id="target_table">
<tbody>
	<tr>
		<th>コード</th>
		<th style='width:200px'>氏名</th>
		<th style='width:200px'>フリガナ</th>
	</tr>
	<tr>
		<td>0001</td>
		<td>浦岡 友也</td>
		<td>ウラオカ トモヤ</td>
	</tr>
	<tr>
		<td>0002</td>
		<td>山村 ひろよ</td>
		<td>ヤマムラ ヒロヨ</td>
	</tr>
	<tr>
		<td>0003</td>
		<td>多岡 冬行</td>
		<td>タオカ フユユキ</td>
	</tr>
	<tr>
		<td>0004</td>
		<td>高田 冬美</td>
		<td>タカタ フユミ</td>
	</tr>
	<tr>
		<td>0005</td>
		<td>内高 友之</td>
		<td>ウチタカ トモユキ</td>
	</tr>
</tbody>
</table>
<div id="result"></div>
<script>
$("#tableinput_action").on("click", function(){
	$("#target_table")
		.tableinput({ "inputwidth": "180px", "maxlength": 50, "col": 1, "class": "inputtd", "inputclass": "tableinput" })
		.tableinput({ "inputwidth": "180px", "maxlength": 50, "col": 2, "class": "inputtd", "inputclass": "tableinput" })
	;

	$(this).prop("disabled", true );
	$("#tableinput_check").prop("disabled", false );
});

$("#tableinput_check").on("click", function(){

	var text = "";
	$("#target_table").tableinputEach(function(i,row){

		// 1行目を処理しない
		if ( i == 0 ) {
			return;
		}

		// row は、td のコレクション
		var td1 = row.eq(1);
		var td2 = row.eq(2);

		// データが変更されていた場合
		if ( td1.data("change") || td2.data("change") ) {

			text +=  i + " : " + td1.text() + " : " + td2.text();
			text +=  " / 元データ : " + td1.data("text") + " : " + td2.data("text") + "<br>";

		}

	});

	$("#result").html(text);

});
</script>

tableinput.js のコード

$.fn.extend({
	tableinput : function(option){

		option = option || { "rowstart":1, "col": 0 };
		if ( typeof option.rowstart ===  'undefined' ) {
			option.rowstart = 1;
		}
		if ( typeof option.col ===  'undefined' ) {
			option.col = 0;
		}

		this.data("tableinput_option_" + option.col, option);

		this.find("tr").each(function(i){

			if ( i < option.rowstart ) {
				return;
			}

			var td = $(this).find("td").eq(option.col);
			if ( typeof option.class !==  'undefined' ) {
				td.addClass( option.class );
			}

			var text = td.text();
			td.data("text", text );

			td.on("click", function(){
				if ( $(this).data("input") != "use" ) {
					// 入力切替えフラグ
					$(this).data("input", "use" );
					// 入力内容
					var text_now = $(this).text();
					// TD の表示を消去
					$(this).text("");
					// 入力を追加
					var input = $("<input>")
							.appendTo($(this)) // TD に追加
							.val(text_now) // テキストセット
							.focus() // フォーカスセット
							// focusout で元に戻す
							.on( "focusout", function(){
								// 現在の入力
								var text = $(this).val();
								// 親 TD
								var td = $(this).parent();
								// データが変更されていたら『変更フラグ』をセット
								if ( text != td.data("text") ) {
									td.data("change", "yes");
								}
								else {
									td.data("change", "");
								}
								// TD に値を戻して 切替えフラグを消去
								td
									.append(text)
									.data("input", "" );
								// INPUT を削除
								$(this).remove();
							});
					if ( typeof option.inputwidth !==  'undefined' ) {
						input.css("width", option.inputwidth );
					}
					if ( typeof option.maxlength !==  'undefined' ) {
						input.prop("maxlength", option.maxlength );
					}
					if ( typeof option.inputclass !==  'undefined' ) {
						input.addClass( option.inputclass );
					}

				}
			});
		});
		// 自分自身を返す
		return this;
	},
	tableinputEach : function(func){

		this.find("tr").each(function(i){

			func(i,$(this).find("td"));

		});

	}
});



関連する記事

テーブルのTDをクリックしたら、INPUT で値を変更可能にして、元の値と違うものにはフラグを立てる処理を絵で書いて説明してみました





posted by lightbox at 2017-10-29 14:03 | プラグイン作成(jQuery) | このブログの読者になる | 更新情報をチェックする

C# : Microsoft Access のテーブルとビューの一覧と任意の SQL を実行するテンプレート

Visual Studio 2012 で作成しています。
(C:\Users\ユーザ\Documents\Visual Studio 2012\Templates\ProjectTemplates に保存します)





Access を参照すると、テーブル一覧とビュー一覧が表示され、テーブルまたはビューをダブルクリックすると、行を表示するテンプレートです。

システムテーブル表示をチェックすると、Access のシステムテーブルを表示しますが、ユーザと権限の管理でシステムテーブルへのアクセス権限が設定できるのは、.mdb ファイルのみになります。

サンプルデータ / 販売管理C.accdb と 販売管理C.mdb



以下はシステムテーブルを表示したものですが、表示できないデータは x となっています。



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SqlUnitAccess2 {
	public partial class Form1 : Form {

		// ファイル選択用
		private OpenFileDialog ofd = new OpenFileDialog();

		// *********************
		// コンストラクタ
		// *********************
		public Form1() {
			InitializeComponent();
		}

		// *********************
		// 画面初期処理
		// *********************
		private void Form1_Load(object sender, EventArgs e) {

			// *********************
			// タイトル表示変更
			// *********************
			this.Text = "SqlUnitAccess";

		}

		// *********************
		// 参照ボタン
		// *********************
		private void ref_Click(object sender, EventArgs e) {

			// *********************
			// ファイル選択
			// *********************
			ofd.Filter = "Access(*.mdb;*.accdb)|*.mdb;*.accdb|すべてのファイル(*.*)|*.*";
			ofd.FilterIndex = 1;
			ofd.Title = "Access データベースを選択してください";
			ofd.RestoreDirectory = true;

			if (ofd.ShowDialog() != DialogResult.OK) {
				return;
			}

			// *********************
			// タイトル表示変更
			// *********************
			this.Text = ofd.FileName;

			// *********************
			// テーブル一覧表示
			// *********************
			loadTables(ofd.FileName);

		}

		// *********************
		// 実行ボタン
		// *********************
		private void action_Click(object sender, EventArgs e) {

			string sql = textBox1.Text;
			// *********************
			// select 実行
			// *********************
			executeReader(ofd.FileName, sql);

		}

		// *********************
		// テーブル一覧ダブルクリック
		// ( CellDoubleClick )
		// *********************
		private void tabel_Select(object sender, DataGridViewCellEventArgs e) {

			// *********************
			// table 名取得
			// *********************
			string value = dataGridTables.Rows[e.RowIndex].Cells[0].Value.ToString();
			textBox1.Text = "select * from " + value;

			// *********************
			// select 実行
			// *********************
			executeReader(ofd.FileName, textBox1.Text);

		}

		// *********************
		// テーブル一覧表示
		// *********************
		private void loadTables(string path) {

			dataGridSelect.DataSource = null;

			using (OleDbConnection myCon = new OleDbConnection()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", path);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
					return;
				}

				DataTable dataTable = null;
				if (checkBoxSysTable.Checked) {
					// *********************
					// 全て
					// *********************
					dataTable = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, null }
					);
				}
				else {
					// *********************
					// TABLE と VIEW をマージ
					// *********************
					dataTable = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, "TABLE" }
					);
					DataTable dataTable2 = myCon.GetOleDbSchemaTable(
						OleDbSchemaGuid.Tables,
						new object[] { null, null, null, "VIEW" }
					);
					dataTable.Merge(dataTable2);
				}

				// 表示しない列は削除
				dataTable.Columns.Remove("TABLE_CATALOG");
				dataTable.Columns.Remove("TABLE_SCHEMA");
				//dataTable.Columns.Remove("TABLE_TYPE");
				dataTable.Columns.Remove("TABLE_GUID");
				dataTable.Columns.Remove("DESCRIPTION");
				dataTable.Columns.Remove("TABLE_PROPID");
				dataTable.Columns.Remove("DATE_CREATED");
				dataTable.Columns.Remove("DATE_MODIFIED");

				// 表示
				dataGridTables.DataSource = dataTable;

				// 接続解除
				myCon.Close();
			}

			// カラム幅の自動調整
			dataGridSelect.AutoResizeColumns();
		}

		// *********************
		// select 実行
		// *********************
		private void executeReader(string path, string sql) {

			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand()) {

				// *********************
				// 接続文字列の作成
				// *********************
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};", path);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
					return;
				}

				// *********************
				// 実行 SQL
				// *********************
				myCommand.CommandText = sql;

				// *********************
				// レコードセット取得
				// *********************
				try {
					using (OleDbDataReader myReader = myCommand.ExecuteReader()) {

						DataTable dataTable = new DataTable();
						dataTable.Load(myReader);
						dataGridSelect.DataSource = dataTable;

						// リーダを使い終わったので閉じる
						myReader.Close();
					}
				}
				catch (Exception ex) {
					myCon.Close();
					MessageBox.Show(this, ex.Message);
					return;
				}

				// 接続解除
				myCon.Close();

			}

			// カラム幅の自動調整
			dataGridSelect.AutoResizeColumns();
		}

		// *********************
		// システム表の表示エラー対応
		// *********************
		private void dataGridSelect_DataError(object sender, DataGridViewDataErrorEventArgs e) {

		}


	}
}




posted by lightbox at 2017-10-29 02:24 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年10月26日


別に納品するわけでは無いので、Android の ListView のカスタマイズなんてこれで十分でしょ / TestArrayAdapter バージョン2

前のバージョンはこちらになりますが、世の中に腐るほどある getView 内の記述を外に出しただけのものでした。しかし、よくよく考えてみると、Adapter 内で セットされているデータを取り出して、そのクラスで引数に渡したらもっと楽だし、View のセットなんかも、Adapter 内ですればいい事に気が付きました。

これで、いろんなテストを気楽に出来る人が増えると思うわけです。

TestArrayAdapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

public class TestArrayAdapter<T> extends ArrayAdapter<T> {

	public interface OnGetViewListener<T> {
		abstract public void onGetViewListener(int position, View convertView, ViewGroup parent, T item);
	}

	private OnGetViewListener listener = null;
	private int resource;
	private LayoutInflater inflater;

	public TestArrayAdapter(Context context, int resource, OnGetViewListener listener) {
		super(context, resource);
		this.listener = listener;
		this.resource = resource;
		this.inflater = (LayoutInflater)context.getSystemService
				(Context.LAYOUT_INFLATER_SERVICE);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if ( listener != null ) {

			if (convertView == null) {
				convertView = inflater.inflate(resource, null);
			}

			T item = this.getItem(position);

			listener.onGetViewListener(position, convertView, parent, item);
			return convertView;
		}
		return super.getView(position, convertView, parent);
	}
}

呼び出し側は、正式には以下のようにインターフェイスにも<WebData> を指定する事で引数の値を WebData として取得できます。しかし、面倒な場合は <WebData> を指定せずに引数を Object でもらってキャストして使えばいいはずです。
		// *******************************
		// ListView で一覧
		// *******************************
		listView = (ListView) MainControl.this.findViewById(R.id.listView);
		arrayAdapter = new TestArrayAdapter<WebData>(MainControl.this, R.layout.item, new TestArrayAdapter.OnGetViewListener<WebData>() {
			@Override
			public void onGetViewListener(int position, View convertView, ViewGroup parent, WebData item) {

				TextView textView;

				textView = convertView.findViewById(R.id.textCode);
				textView.setText(item.社員コード);

				textView = convertView.findViewById(R.id.textName);
				textView.setText(item.氏名);

				textView = convertView.findViewById(R.id.textType);
				textView.setText(item.所属名);
			}
		});
		listView.setAdapter(arrayAdapter);


画面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">


    <TextView
        android:id="@+id/textCode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/textName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="23sp"/>

    <TextView
        android:id="@+id/textType"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="6dp"
        android:textSize="18sp"/>


</LinearLayout>




WebData
public class WebData {

	String 社員コード;
	String 氏名;
	String フリガナ;
	String 所属;
	String 性別;
	int 給与;
	String 手当;
	String 管理者;
	String 生年月日;
	String 生年月日2;
	String 所属名;

	@Override
	public String toString() {
		return 氏名;
	}
}


WebData は 『Java : Class 構造より、update 文を作成する』でも使用しています



タグ:android
posted by lightbox at 2017-10-26 20:00 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

2017年10月21日


Java : Class 構造より、update 文を作成する

作ったのは Android Studio です。

以下のクラスですが、一目して ListView 用のクラスである事が解ると思います( toString が表示用 )。また、JSON を Google Gson でデシリアライズする事を想定しているので、C 言語の構造体のような単純な定義です。

WebData クラス
public class WebData {

	String 社員コード;
	String 氏名;
	String フリガナ;
	String 所属;
	String 性別;
	int 給与;
	String 手当;
	String 管理者;
	String 生年月日;
	String 生年月日2;
	String 所属名;

	@Override
	public String toString() {
		return 氏名;
	}
}


この Class のインスタンスに、画面から入力データをセットし、Class 構造を取得して Update 文の where 以降以外を作成するコードが以下です。

buildUpdate メソッド
	public String buildUpdate(String table, Object obj, Class<?> cls) {
		String result = "";

		Field[] flds = cls.getDeclaredFields();
		String type = "";
		String col = "";
		String val = "";
		for( Field fld : flds ) {

			// null 値の場合無視
			try {
				if ( fld.get( obj ) == null ) continue;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			// フィールド名( 列名に一致させた Class 定義 )
			col = fld.getName();
			try {
				// 値( 文字列 )
				val = fld.get( obj ).toString();

			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			// データ型 : この場合、int かそれ以外
			type = fld.getType().getName();

			if (!result.equals("")) {
				result += ",";
			}
			if (type.equals("int")) {
				if ( val.equals("") ) {
					result += String.format(" %s = null ", col);
				}
				else {
					result += String.format(" %s = %s ", col, val);
				}
			}
			else {
				if ( val.equals("") ) {
					result += String.format(" %s = null ", col);
				}
				else {
					result += String.format(" %s = '%s' ", col, val);
				}
			}

		}

		result = String.format("update %s set %s", table, result );

		return result;
	}

※ 本来、StringBuilder 等を使用するところを += 演算子を使用しているのはコードを見やすくする為です

エラー処理は最低限で作られていますが、重要なのは Field オブジェクトなので、ご理解下さい。

冒頭に、cls.getDeclaredFields() で、定義されている Field オブジェクトの配列を取得して、ループ処理しているだけです。

引数より、Object として、WebData のインスタンスが渡されて、fld.get( obj ).toString() でデータを取得し、fld.getName() として取得された文字列は列名と一致する事を想定しています。

あとは、fld.getType().getName() で、int かそれ以外でシングルクォートの使い方を決めるわけです。

以下は、その呼び出しコードです。
		WebData curInput = new WebData();

		String code = helper.getTextViewString(R.id.textViewCode);

		// 使用しないフィールドには null をセットする
		curInput.社員コード = null;
		curInput.所属名 = null;
		curInput.生年月日2 = null;

		curInput.氏名 = helper.getEditTextString(R.id.editText1);
		curInput.フリガナ = helper.getEditTextString(R.id.editText2);
		curInput.所属 = helper.getEditTextString(R.id.editText3);
		curInput.給与 = Integer.parseInt(helper.getEditTextString(R.id.editText5));
		curInput.手当 = helper.getEditTextString(R.id.editText6);
		curInput.管理者 = helper.getEditTextString(R.id.editText7);
		curInput.生年月日 = helper.getEditTextString(R.id.editTexBirth);

		curInput.性別 = ((Spinner)(helper.mainActivity).findViewById(R.id.spinner)).getSelectedItemPosition()+"";

		String update = helper.buildUpdate("社員マスタ", curInput, WebData.class );
		String text = update + String.format(" where 社員コード = '%s' ", code );



null を設定して、除外するフィールドを決めています。なので、このコードでは意図的に空文字を文字列の列にセットする事ができません。そういう場合は、仕様を追加します。



タグ:java Reflect
posted by lightbox at 2017-10-21 01:15 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

2017年10月12日


Oracle : SQL Plus で、デッドロックテスト ( ORA-00060 )

SQL Plus では、意図的に commit を実行しない限りトランザクションが終わらないので、二つの行を A クライアントと B クライアントで取り合うように UPDATE 文を実行すると、デッドロックを発生させる事ができます。

デッドロック(ORA-00060)が発生した場合、そちらのクライアントで rollback を実行すると、もう片方では更新が完了するので、そちらで commit を実行して更新を確定させます

▼ 対象レコード


A クライアントの SQL
update 商品分類マスタ set 名称 = 'A-野菜'
where 商品分類 = 'A01';

update 商品分類マスタ set 名称 = 'A-果物'
where 商品分類 = 'A02';

B クライアントの SQL
update 商品分類マスタ set 名称 = 'B-果物'
where 商品分類 = 'A02';

update 商品分類マスタ set 名称 = 'B-野菜'
where 商品分類 = 'A01';

実行の経過

A クライアントも B クライアントも違う行を更新して、それぞれ行は更新されますが、commit で確定されていないので実際の更新は行われていません。しかし、これらのレコードに対するロックが有効になります。





次の実行で更新が待機になり、その次の更新でデッドロックが起こり、A クライアントで待機が解除されてデッドロックのステータスが返ります。





デッドロック(ORA-00060)が発生したので、更新はやりなおしになります。いったん rollback を実行して次の更新に備えます( このような処理を何回までリトライするかはシステムであらかじめ決めておきます )



rollback が実行されてロックされていた行が開放されたので、B クライアントでは更新が完了するので、commit で確定させます。





posted by lightbox at 2017-10-12 14:36 | Oracle | このブログの読者になる | 更新情報をチェックする

テーブルのTDをクリックしたら、INPUT で値を変更可能にして、元の値と違うものにはフラグを立てる処理を絵で書いて説明してみました



とにかく、複雑になってしまったので絵にしてみました。

デモページ(送信ボタンで一覧表示した後でデモ)


ソースコードはこんな感じ
	$("#data .row_data").each(function(i){

		var td = $(this).find("td").eq(2);

		td.css( 
			{ "text-decoration":"underline", "cursor":"crosshair", "background-color" : "pink" }
		);

		// 入力内容
		var text = td.text();
		// 入力内容を保存
		td.data("text", text );

		td.on("click", function(){
			if ( $(this).data("input") != "use" ) {
				// 入力切替えフラグ
				$(this).data("input", "use" );

				// 入力内容
				var text_now = $(this).text();

				// TD の表示を消去
				$(this).text("");

				// 入力を追加
				$("<input>")
						.appendTo($(this))		// TD に追加
						.val(text_now)			// テキストセット
						.focus()			// フォーカスセット
						// focusout で元に戻す
						.on( "focusout", function(){

							// 現在の入力
							var text = $(this).val();

							// 親 TD
							var td = $(this).parent();

							// データが変更されていたら『変更フラグ』をセット
							if ( text != td.data("text") ) {
								td.data("change", "yes");
								td.css("background-color","silver");
							}
							else {
								td.data("change", "");
								td.css("background-color","pink");
							}

							// TD に値を戻して 切替えフラグを消去
							td
								.append(text)
								.data("input", "" );

							// INPUT を削除
							$(this).remove();


						});

			}

		});

	});



posted by lightbox at 2017-10-12 03:17 | jQuery | このブログの読者になる | 更新情報をチェックする
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 終わり