HEXA BLOG
ヘキサブログ
プログラム
敵とか武器とかアイテムとか その4
先日、人生で初めてのスノーボードに行ったら、
偶然取材できていたラジオ局の人に
「今ラジオの企画で、最近の若者に取材をしてるんですが、大学生ですか?」
って話しかけられました。
溢れ出る若さが抑えきれないようです。
こんにちは、だっちです。
(雪ではしゃいで小さい雪だるまを作っていたから話しかけられたわけじゃないはず!
さて、前回に引き続きExcelで作成したデータから、
ゲーム内で扱いやすい形に変換するためのプログラムを実装していこうと思います。
前回は「クラスファイルの生成」を行うところまで出来たので、
今回は予定通り「データファイルの書き出し」を行っていきたいと思います。
ファイルの形式は、とりあえずXML形式で書き出していこうと思います。
前回までのプログラムを改良して、データファイルを書き出してきます。
データはこんな感じで用意してみました。

コードは長くなってしまったので一番下に載せておきます。
実際に生成されたXMLファイルはこんな感じです。

これで、「データファイルを書き出す」事ができましたね!
ただ、単純にXMLファイルを書き出すだけならExcel標準の機能でも行うことが出来ますし、
前回生成したクラスファイルも活用していなくてせっかく実装した恩恵が少ないですね。
次回からはもう少し便利になるように拡張していこうと思います。
ではでは~
以下ソースコードです。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NPOI.SS.UserModel;
using System.Xml;
namespace NPOITest
{
class Program
{
// クラス情報
private class ClassInfo
{
public string name { get; } //!< クラス名
public string desc { get; } //!< クラス説明
public List memberVariableInfos { get; } //!< メンバ変数情報
// @brief コンストラクタ
// @param [in] name クラス名
// @param [in] desc クラス説明
// @param [in] memberVariableInfos メンバ変数情報
public ClassInfo(string name, string desc, List memberVariableInfos)
{
this.name = name;
this.desc = desc;
this.memberVariableInfos = memberVariableInfos;
}
}
// メンバ変数情報
private class MemberVariableInfo
{
public string name { get; } //!< 変数名
public string type { get; } //!< 型
public string desc { get; } //!< 変数説明
// @brief コンストラクタ
// @param [in] name 変数名
// @param [in] type 型
// @param [in] desc 変数説明
public MemberVariableInfo(string name, string type, string desc)
{
this.name = name;
this.type = type;
this.desc = desc;
}
}
// データ
private class Data
{
public List records { get; } //!< レコード
// @brief コンストラクタ
// @param [in] records レコード
public Data(List records)
{
this.records = records;
}
}
// データ1レコード
private class Record
{
public List values { get; } //!< 値
// @brief コンストラクタ
// @param [in] values 値
public Record(List values)
{
this.values = values;
}
}
private const string TYPEDEF_SHEET_NAME = "typedef"; //!< 「型情報定義」シート名
private const string DATA_SHEET_NAME = "data"; //!< 「データ」シート名
private const int DATA_NAME_ROW = 0; //!< データ名行
private const int DATA_NAME_CELL = 1; //!< データ名列
private const int DATA_DESC_ROW = 1; //!< データ説明行
private const int DATA_DESC_CELL = 1; //!< データ説明列
private const int MEMBER_VARIABLE_START_ROW = 10; //!< メンバ変数開始行
private const int MEMBER_VARIABLE_NAME_CELL = 1; //!< メンバ変数名列
private const int MEMBER_VARIABLE_TYPE_CELL = 2; //!< メンバ変数型列
private const int MEMBER_VARIABLE_DESC_CELL = 3; //!< メンバ変数説明列
private const int MEMBER_VARIABLE_MAX = 1024; //!< メンバ変数最大許容数
private const int DATA_START_ROW = 1; //!< データ開始業
private const int DATA_START_CELL = 1; //!< データ開始列
private const int DATA_MAX = 1024; //!< データ最大許容数
// @brief エントリポイント
public static void Main(string[] args)
{
// エクセルファイル入力受付
Console.Write("Prease input excel file path : ");
var srcPath = Console.ReadLine();
// 読み込み
ClassInfo classInfo = null;
readExcelFile(srcPath, out classInfo);
Data data = null;
readExcelFile(srcPath, classInfo, out data);
// クラスファイル書き出し先入力受付
Console.Write("Prease input class file output directory : ");
var outDirectory = Console.ReadLine();
// 書き出し
writeClassFile(outDirectory, classInfo);
writeDataFile(outDirectory, classInfo, data);
}
// @brief エクセルファイルの読み込み
// @param [in] srcPath 読み込みファイル名
// @param [out] classInfo クラス情報
// @return なし
private static void readExcelFile(string srcPath, out ClassInfo classInfo)
{
classInfo = null;
// ファイル存在確認
if( !File.Exists(srcPath) ) {
Console.WriteLine("file not exists.");
return;
}
var className = string.Empty;
var classDesc = string.Empty;
var memberVariableInfos = new List();
var records = new List();
using( var fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) ) {
var workbook = WorkbookFactory.Create(fs);
// 中にあるシートを順番に取得
foreach( ISheet sheet in workbook ) {
if( sheet == null ) continue;
// シート名表示
Console.WriteLine(" Name : " + sheet.SheetName);
// シートの名前が「型情報定義」シート名だったら、型情報を読み込み
if( sheet.SheetName == TYPEDEF_SHEET_NAME ) {
Console.WriteLine();
Console.WriteLine("Data");
// データ名を取得
className = getCellValue(sheet, DATA_NAME_ROW, DATA_NAME_CELL);
if( string.IsNullOrWhiteSpace(className) ) {
Console.WriteLine("DataName acquisition failed...");
}
else {
Console.WriteLine(" Name : " + className);
}
// データ説明を取得
classDesc = getCellValue(sheet, DATA_DESC_ROW, DATA_DESC_CELL);
if( string.IsNullOrWhiteSpace(classDesc) ) {
Console.WriteLine("DataDesc acquisition failed...");
}
else {
Console.WriteLine(" Desc : " + classDesc);
}
// メンバ変数を取得
Console.WriteLine("MemberVariables");
for( int i = 0, row = MEMBER_VARIABLE_START_ROW; i < MEMBER_VARIABLE_MAX; ++i, ++row ) {
// メンバ変数名を取得
var memberName = getCellValue(sheet, row, MEMBER_VARIABLE_NAME_CELL);
if( string.IsNullOrWhiteSpace(memberName) ) {
Console.WriteLine("MemberName acquisition failed...");
// メンバ変数名が空欄だったら終了と判断
Console.WriteLine("End Of Member Variables");
break;
}
Console.WriteLine(" [" + i + "]");
Console.WriteLine(" Name : " + memberName);
// メンバ変数型を取得
var memberType = getCellValue(sheet, row, MEMBER_VARIABLE_TYPE_CELL);
if( string.IsNullOrWhiteSpace(memberType) ) {
// メンバ変数名が空欄だったら終了と判断
Console.WriteLine("MemberType acquisition failed...");
}
else {
Console.WriteLine(" Type : " + memberType);
}
// メンバ変数説明を取得
var memberDesc = getCellValue(sheet, row, MEMBER_VARIABLE_DESC_CELL);
if( string.IsNullOrWhiteSpace(memberDesc) ) {
// メンバ変数名が空欄だったら終了と判断
Console.WriteLine("MemberDesc acquisition failed...");
}
else {
Console.WriteLine(" Desc : " + memberDesc);
}
memberVariableInfos.Add(new MemberVariableInfo(memberName, memberType, memberDesc));
}
}
}
}
classInfo = new ClassInfo(className, classDesc, memberVariableInfos);
}
// @brief エクセルファイルの読み込み
// @param [in] srcPath 読み込みファイル名
// @param [in] classInfo クラス情報
// @param [out] data データ
// @return なし
private static void readExcelFile(string srcPath, ClassInfo classInfo, out Data data)
{
data = null;
// クラス情報有効性チェック
if( classInfo == null ||
classInfo.memberVariableInfos == null ||
classInfo.memberVariableInfos.Count <= 0 ) {
Console.WriteLine("\"classInfo\" is invalid.");
return;
}
// ファイル存在確認
if( !File.Exists(srcPath) ) {
Console.WriteLine("file not exists.");
return;
}
using( var fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) ) {
var workbook = WorkbookFactory.Create(fs);
// 中にあるシートを順番に取得
foreach( ISheet sheet in workbook ) {
if( sheet == null ) continue;
// シート名表示
Console.WriteLine(" Name : " + sheet.SheetName);
// シートの名前が「データ」シート名だったら、レコードを読み込み
if( sheet.SheetName == DATA_SHEET_NAME ) {
Console.WriteLine();
Console.WriteLine("Records");
var valueMax = classInfo.memberVariableInfos.Count;
var records = new List();
// レコード数分ループ
for( int rowIndex = DATA_START_ROW, recordCount = 0; recordCount < DATA_MAX; ++rowIndex, ++recordCount ) {
var values = new List();
var isEndRead = false;
// メンバ変数分ループ
for( int cellIndex = DATA_START_CELL, valueCount = 0; valueCount < valueMax; ++cellIndex, ++valueCount ) {
// セルの内容取得
var cellStr = getCellValue(sheet, rowIndex, cellIndex);
// 1セル目が空白なら終了扱い
if( valueCount == 0 &&
string.IsNullOrEmpty(cellStr) ) {
isEndRead = true;
break;
}
Console.Write(cellStr + ", ");
values.Add(cellStr);
}
if( isEndRead ) break;
Console.WriteLine();
records.Add(new Record(values));
}
data = new Data(records);
}
}
}
}
// @brief クラスファイルの書き出し
// @param [in] outDirectory 書き出し先ディレクトリ
// @param [in] classInfo クラス情報
// @return なし
private static void writeClassFile(string outDirectory, ClassInfo classInfo)
{
// 入力情報が不正なら終了
if( string.IsNullOrWhiteSpace(outDirectory) ) {
Console.WriteLine("outDirectory is invalid....");
return;
}
if( classInfo == null ||
string.IsNullOrWhiteSpace(classInfo.name) ||
string.IsNullOrWhiteSpace(classInfo.desc) ||
classInfo.memberVariableInfos == null ) {
Console.WriteLine("classInfo is invalid...");
return;
}
// 指定ディレクトリがなければ作成
if( Directory.Exists(outDirectory) ) {
Directory.CreateDirectory(outDirectory);
}
// ソースコード作成
var sourceCode = new StringBuilder();
// クラス開始
sourceCode.AppendLine("// @class " + classInfo.name);
sourceCode.AppendLine("// @brief " + classInfo.desc);
sourceCode.AppendLine("public class " + classInfo.name);
sourceCode.AppendLine("{");
// プロパティ開始
foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
if( memberVariableInfo == null ||
string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;
sourceCode.AppendLine(" public " + memberVariableInfo.type + " " + memberVariableInfo.name + " { get; } //!< " + memberVariableInfo.desc);
}
sourceCode.AppendLine();
// プロパティ終了
// コンストラクタ開始
sourceCode.AppendLine(" // @brief コンストラクタ");
// コンストラクタコメント
foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
if( memberVariableInfo == null ||
string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;
sourceCode.AppendLine(" // @param [in] " + memberVariableInfo.name + " " + memberVariableInfo.desc);
}
// 引数
var constructorArgs = new StringBuilder();
foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
if( memberVariableInfo == null ||
string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;
constructorArgs.Append(memberVariableInfo.type + " " + memberVariableInfo.name + ", ");
}
// 最後の不要な「, 」削除
constructorArgs.Remove(constructorArgs.Length - 2, 2);
sourceCode.AppendLine(" public " + classInfo.name + "(" + constructorArgs.ToString() + ")");
sourceCode.AppendLine(" {");
foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
if( memberVariableInfo == null ||
string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;
sourceCode.AppendLine(" this." + memberVariableInfo.name + " = " + memberVariableInfo.name + ";");
}
sourceCode.AppendLine(" }");
// コンストラクタ終了
sourceCode.AppendLine("}");
// クラス終了
// 書き出し
using( var sw = new StreamWriter(outDirectory + classInfo.name + ".cs", false, new UTF8Encoding(true)) ) {
sw.Write(sourceCode.ToString());
}
}
// @brief データファイルの書き出し
// @param [in] outDirectory 書き出し先ディレクトリ
// @param [in] classInfo クラス情報
// @param [in] data データ
// @return なし
private static void writeDataFile(string outDirectory, ClassInfo classInfo, Data data)
{
// 入力情報が不正なら終了
if( string.IsNullOrWhiteSpace(outDirectory) ) {
Console.WriteLine("outDirectory is invalid....");
return;
}
if( classInfo == null ||
classInfo.memberVariableInfos == null ||
classInfo.memberVariableInfos.Count <= 0 ) {
Console.WriteLine("classInfo is invalid...");
return;
}
if( data == null ||
data.records == null ||
data.records.Count <= 0 ) {
Console.WriteLine("data is invalid...");
return;
}
// 指定ディレクトリがなければ作成
if( Directory.Exists(outDirectory) ) {
Directory.CreateDirectory(outDirectory);
}
// ドキュメント作成
var xmlDocument = new XmlDocument();
// 定義、ルートノードを作成してドキュメントに追加
var xmlDeclaration = xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null);
xmlDocument.AppendChild(xmlDeclaration);
var xmlRoot = xmlDocument.CreateElement("root");
xmlDocument.AppendChild(xmlRoot);
var memberVariableInfos = classInfo.memberVariableInfos.ToArray();
// レコードを全てルートに追加
foreach( var record in data.records ) {
var xmlRecord = xmlDocument.CreateElement(classInfo.name);
var values = record.values.ToArray();
// 値を全てレコードに追加
for( var i = 0; i < memberVariableInfos.Length && i < values.Length; ++i ) {
var xmlValue = xmlDocument.CreateElement(memberVariableInfos[i].name);
xmlValue.InnerText = values[i];
xmlRecord.AppendChild(xmlValue);
}
// ルートに追加
xmlRoot.AppendChild(xmlRecord);
}
// ファイルに保存
using( var sw = new StreamWriter(outDirectory + classInfo.name + ".xml", false, new UTF8Encoding(true)) ) {
xmlDocument.Save(sw);
}
}
// @brief セルの値を取得
// @param [in] sheet シート
// @param [in] rowIndex 行インデックス
// @param [in] cellIndex 列インデックス
// @return セルの値
private static string getCellValue(ISheet sheet, int rowIndex, int cellIndex)
{
if( sheet == null ) return string.Empty;
// 行を取得
var row = sheet.GetRow(rowIndex);
if( row == null ) return string.Empty;
// 行からセルを取得
var cell = row.GetCell(cellIndex);
if( cell == null ) return string.Empty;
// セルが取得できたら中身を文字列化
return cell.ToString();
}
}
}
CATEGORY
- about ヘキサ (166)
- 部活動 (6)
- CG (18)
- プロジェクトマネジメント (1)
- 研修 (5)
- 美学 (1)
- いいモノづくり道 (227)
- 採用 -お役立ち情報も- (149)
- プログラム (189)
- デザイン (99)
- ゲーム (273)
- 日記 (1,104)
- 書籍紹介 (113)
- その他 (889)
- 就活アドバイス (20)
- ラーメン (3)
- ライフハック (25)
- イベント紹介 (10)
- 料理 (23)
- TIPS (7)
- 怖い話 (3)
- サウンド (6)
- 子育て (1)
- 筋トレ (1)
- NicO (3)
- MakeS (9)
- 商品紹介 (21)
- アプリ紹介 (31)
- ソフトウェア紹介 (33)
- ガジェット紹介 (12)
- サイト紹介 (10)
- 研究・開発 (35)
- 回路図 (4)
- アナログゲーム (40)
- 交流会 (21)
- 報告会 (3)
- インフラ (25)
- グリとブラン (6)
- カメラ (9)
- クラフト (27)
- 部活 (14)
- 画伯 (15)
- カレー (6)
- 音楽(洋楽) (6)
- 映画・舞台鑑賞 (43)
- 飼育 (5)
- いぬ (8)
- ねこ (19)
ARCHIVE
- 2025年
- 2024年
- 2023年
- 2022年
- 2021年
- 2020年
- 2019年
- 2018年
- 2017年
- 2016年
- 2015年
- 2014年
- 2013年
- 2012年
- 2011年
- 2010年
- 2009年
- 2008年
- 2007年




