6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Excelで支給された元データを極力加工せず、JSONとjQueryを用いて、いかにして早くHTMLを作るか?

Last updated at Posted at 2017-02-16

HTML、JavaScriptを扱う人を対象に投稿しています。

要件

<ul>
	<li>カテゴリA
		<ul>
			<li><a href="DUMMY">カテゴリAの商品1</a></li>
			<li><a href="DUMMY">カテゴリAの商品2</a></li>
			<li><a href="DUMMY">カテゴリAの商品3</a></li>
		</ul>
	</li>
	<li>カテゴリB
		<ul>
			<li><a href="DUMMY">カテゴリBの商品1</a></li>
			<li><a href="DUMMY">カテゴリBの商品2</a></li>
			<li><a href="DUMMY">カテゴリBの商品3</a></li>
		</ul>
	</li>
</ul>

といった、ネストされた<ul><li>のHTMLを作るという要件で、カテゴリ、URL、商品名が、みっちりぎっしり大量に記載されたExcelファイルを渡されたとします。
そのExcelファイルが下記の書式(1行につき1商品)だったら、どうしますか?

1.png

6.png

実装方法

まさか手作業でHTML化するわけにはいきません。
ExcelのデータをJSONに書き出して、JavaScriptでHTMLを組み立てる方法を検討しました。
(他の言語を用いれば、もっと早くできるかもしれませんが、HTML、jQueryを扱う人向けの提案です)

問題はネストの部分。
このExcelの書式では、下記のような入れ子のJSONを作ることが難しそうです。

[
	{
		"category":"カテゴリA",
		"product":[
			{"name":"カテゴリAの商品1", "url":"http://XXX/a_01.html"},
			{"name":"カテゴリAの商品2", "url":"http://XXX/a_02.html"},
			{"name":"カテゴリAの商品3", "url":"http://XXX/a_03.html"}
		]
	},
	{
		"category":"カテゴリB",
		"product":[
			{"name":"カテゴリBの商品1", "url":"http://XXX/b_01.html"},
			{"name":"カテゴリBの商品2", "url":"http://XXX/b_02.html"},
			{"name":"カテゴリBの商品3", "url":"http://XXX/b_03.html"}
		]
	},
	{
		"category":"カテゴリC",
		"product":[
			{"name":"カテゴリCの商品1", "url":"http://XXX/c_01.html"},
			{"name":"カテゴリCの商品2", "url":"http://XXX/c_02.html"},
			{"name":"カテゴリCの商品3", "url":"http://XXX/c_03.html"}
		]
	}
]

そこで入れ子のJSONを作らずに、Excel1行につき、1オブジェクトとしたJSONからHTMLを出力させます。

作業1. ExcelデータのJSON化

ExcelデータをJSON化するには様々な手段がありますが、以下の方法を用いました。

  1. 元Excelのラベル(「カテゴリ名」「商品名」「URL」)をキーに変更(「category」「name」「url」)
    2.png
  2. 元ExcelをCSVデータとして保存
  3. CSV to JSON - CSVJSON http://www.csvjson.com/csv2json でコンバート
    3.png

下記のJSONファイルを素早く準備できました。

sample.json

[
  {
    "category": "カテゴリA",
    "name": "カテゴリAの商品1",
    "url": "http://XXX/a_01.html"
  },
  {
    "category": "カテゴリA",
    "name": "カテゴリAの商品2",
    "url": "http://XXX/a_02.html"
  },
  {
    "category": "カテゴリA",
    "name": "カテゴリAの商品3",
    "url": "http://XXX/a_03.html"
  },
  {
    "category": "カテゴリB",
    "name": "カテゴリBの商品1",
    "url": "http://XXX/b_01.html"
  },
  {
    "category": "カテゴリB",
    "name": "カテゴリBの商品2",
    "url": "http://XXX/b_02.html"
  },
  {
    "category": "カテゴリB",
    "name": "カテゴリBの商品3",
    "url": "http://XXX/b_03.html"
  },
  {
    "category": "カテゴリC",
    "name": "カテゴリCの商品1",
    "url": "http://XXX/c_01.html"
  },
  {
    "category": "カテゴリC",
    "name": "カテゴリCの商品2",
    "url": "http://XXX/c_02.html"
  },
  {
    "category": "カテゴリC",
    "name": "カテゴリCの商品3",
    "url": "http://XXX/c_03.html"
  }
]

作業2. HTML、jQueryコードの作成

sample.jsonからHTMLを組み立てるコードを書きます。

HTML、jQuery

<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title></title>
<script
  src="https://code.jquery.com/jquery-3.1.1.js"
  integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
  crossorigin="anonymous"></script>
</head>
<script>
$.getJSON('sample.json', {}, function(json){

	// 変数の宣言
	var htmlString = '';
	var htmlStringWrap = '';
	var prevCategory = '';
	var category = '';

	$.each(json, function(i, obj){

		// 直前のループにおける変数「category」を「prevCategory」に代入(ループ初回時の値は初期値の「''」)
		prevCategory = category;

		// キー「category」の値を変数「category」に代入
		category = obj.category;

		// ループのたびに変数「htmlStringWrap」を初期化
		htmlStringWrap = '';

		// 【第1階層の<li>を作成】「prevCategory」と「category」の値が異なる場合に、<ul>を内包する<li>を、変数「htmlStringWrap」にセット
		// ループ初回の「\n</ul>\n</li>」はinvalidなHTMLのため、無視される
		if (category !== prevCategory) { 
			htmlStringWrap = '\n</ul>\n</li>\n<li>' + category + '\n<ul>';
		}

		// 【第2階層の<li>を作成】ループを回し、obj.url と obj.name に基づいたリンクを内包する<li>を、変数「htmlStringWrap」と連結して、変数「htmlString」に順繰りに追加
		htmlString += htmlStringWrap + '\n<li><a href="' + obj.url + '">' + obj.name + '</a></li>';

	});

	// JSONを元に形成したHTML(変数「htmlString」)を<ul id="link">~</ul>内に追加
	$('#link').html(htmlString);

});
</script>
</head>
<body>
<ul id="link">
</ul>
</body>
</html>

出力結果

<ul id="link">


<li>カテゴリA
<ul>
<li><a href="http://XXX/a_01.html">カテゴリAの商品1</a></li>
<li><a href="http://XXX/a_02.html">カテゴリAの商品2</a></li>
<li><a href="http://XXX/a_03.html">カテゴリAの商品3</a></li>
</ul>
</li>
<li>カテゴリB
<ul>
<li><a href="http://XXX/b_01.html">カテゴリBの商品1</a></li>
<li><a href="http://XXX/b_02.html">カテゴリBの商品2</a></li>
<li><a href="http://XXX/b_03.html">カテゴリBの商品3</a></li>
</ul>
</li>
<li>カテゴリC
<ul>
<li><a href="http://XXX/c_01.html">カテゴリCの商品1</a></li>
<li><a href="http://XXX/c_02.html">カテゴリCの商品2</a></li>
<li><a href="http://XXX/c_03.html">カテゴリCの商品3</a></li></ul></li></ul>

4.png

補足

ループ初回の「</ul></li>」はinvalidなHTMLのため、無視されます。

<ul id="link">
</ul>
</li>
<li>カテゴリA
<ul>
<li><a href="http://XXX/a_01.html">カテゴリAの商品1</a></li>
<li><a href="http://XXX/a_02.html">カテゴリAの商品2</a></li>
<li><a href="http://XXX/a_03.html">カテゴリAの商品3</a></li>
</ul>
</li>
【中略】
<li>カテゴリC
<ul>
<li><a href="http://XXX/c_01.html">カテゴリCの商品1</a></li>
<li><a href="http://XXX/c_02.html">カテゴリCの商品2</a></li>
<li><a href="http://XXX/c_03.html">カテゴリCの商品3</a></li></ul></li></ul>

にはなりません。

参照: innerHTML や jQuery.html() は HTMLをそのまま取得できるわけではない

静的HTMLとして保存したい場合

2つの方法をとることができます。

  • ブラウザの「名前を付けて保存」で、ファイルの種類を「ウェブページ、完全」とすると、HTMLが出力された状態のファイルを取得できます。
  • 開発ツールでDOM要素を右クリック「Copy > Copy outerHTML」し、必要な範囲をコピー。
    5.png

支給されたデータを、あれやこれや加工してしまうと、データに齟齬が生じてしまうのではないかと考えました。
支給データはなるべくいじらず、省エネモードで、さくさくとHTMLを作成する、そんなコーダーでありたいと思います。

6
11
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?