- ベストアンサー
Excelから配列コードの作成
Excelなどで作成した表の値を初期値とする配列をコードしないといけないのですが、 きれいに作成してくれるソフト・マクロなどはないでしょうか? 配列の要素数は多いので(300くらい)、 1行に何要素か並べ、可読性がよくなるように。 というのが条件です。 よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
汎用的なマクロは、網羅するケースが非常に広くなって難しいでしょうが、特定の場合はマクロを作るのはそれほど難しくないと思います。 実際の仕事にも利用しています。 以下VBAのサンプルです(インデントは崩れていますが)。 参考にしてください。 エクセルのセルA1に配列の説明、A2に配列名、A3に配列の要素数、A4にソースコードにしたときの一行に入る要素数、A5以下に実際の要素を入れます。 --- ここからサンプル --- Private Sub GenSourceCodeButton_Click() '========================================== 'エクセルのデータからC/C++のソースコード作成 '========================================== ' *** 変数 *** Dim strTableTitle As String Dim strVarName As String Dim strOutputFileName As String Dim strOutput As String Dim iCount As Integer Dim iVal As Integer Dim iNumPerLine As Integer Dim iNumItem As Integer ' *** プログラム開始 ' 1.ファイル名取得 strOutputFileName = Application.GetSaveAsFilename("table.cpp", "(*.cpp),*.cpp", , "C++ ソースコード ファイル名") Open strOutputFileName For Output As #1 ' 2.頭の部分 Print #1, "// VBAによるエクセルからの自動作成" strOutput = "// 元ファイル " + ThisWorkbook.Name Print #1, strOutput strOutput = "// 作成日時:" + Format(Date) + " " + Format(Time) Print #1, strOutput strOutput = "// テーブル名:" + Trim$(Worksheets("テーブル").Cells(1, "A")) Print #1, strOutput strOutput = Trim$(Worksheets("テーブル").Cells(2, "A")) + " =" Print #1, strOutput Print #1, "{" '3.テーブル strOutput = " " iNumItem = Val(Trim$(Worksheets("テーブル").Cells(3, "A"))) iNumPerLine = Val(Trim$(Worksheets("テーブル").Cells(4, "A"))) For iCount = 0 To iNumItem iVal = Val(Trim$(Worksheets("テーブル").Cells(iCount + 5, "A"))) strOutput = strOutput + Format(iVal) If ((iCount Mod iNumPerLine) = (iNumPerLine - 1)) Then If (iCount <> (iNumItem - 1)) Then strOutput = strOutput + ", " Print #1, strOutput strOutput = " " Else Print #1, strOutput '最後の行 End If Else strOutput = strOutput + ", " End If Next iCount Print #1, "};" '4. 終了 Close #1 MsgBox ("ファイル作成終了") End Sub
その他の回答 (4)
こんにちは。 見当違いの内容でしたらすみません。 一例として、Excelのマクロを使用して配列定義のテキストソースを作成する サンプルを作ってみました。 (注:ただし、2次元配列限定になります。) 当方は、Excel 2000で作ってました。 (注:他のバージョンで上手く動作するかは判りません。) 宜しければ試してみて下さい。 配列が1次元のみだった場合、あるいは上手く動作しなかった場合などは、 適宣マクロ等を修正してみて下さい。 ■処理の概要 ワークシートで、配列の配列名、型、要素数および、各要素のデータを設定し、 コマンドボタンをクリックすると、設定した配列構造を定義した、Cソース用の テキストファイルを作成する。 ■ワークシート[Sheet1]の構成 A B C D E ・・・・・・ 1 配列の変数名 array [ソース作成] ←コマンドボタン 2 配列の型 unsigned long 3 1次元目の要素数 20 4 2次元目の要素数 15 5 配列の要素位置 0 1 2 3 ・・・・・・ 6 0 1 2 3 4 ・・・・・・ 7 1 101 102 103 104 ・・・・・・ 8 2 201 202 203 204 ・・・・・・ 9 3 301 302 303 304 ・・・・・・ 10 4 401 402 403 404 ・・・・・・ : : : : : : ・・・・・・ : : : : : : ・・・・・・ ※添付画像にキャプチャ画像を付けました(画像の方が判り易いかも) <セルの内容> ◎B1 : 文字列 : 配列の変数名を入力する。 ◎B2 : 文字列 : 配列の型名を入力する。 ◎B3 : 数値 : 配列の1次元目の要素数を入力する。 ◎B4 : 数値 : 配列の2次元目の要素数を入力する。 ◎A6~下方向 : 式 : 下記<セルの設定式>参照 ◎B5~右方向 : 式 : 下記<セルの設定式>参照 ◎B6~矩形範囲 : 数値 : 配列の各要素のデータを入力する。 <セルの設定式> ◎A6以降(下方向)のセルの設定式 : =IF(ROW()-6<$B$3,ROW()-6,"") ◎B5以降(右方向)のセルの設定式 : =IF(COLUMN()-2<$B$4,COLUMN()-2,"") ============================== ■マクロソース 注)ソース上にはインデントのため全角スペースを入れています。 もし、ご使用の際はタブなどに一括置換して下さい。 ◎ワークシート[Sheet1]のコードモジュール '************************************************* '* コマンドボタン [ソース作成]のクリック時の処理 '************************************************* Private Sub CommandButton1_Click() Call MakeArrayText End Sub ◎標準モジュール '************************************************* '* MakeArrayText(配列定義のテキストソース作成) '************************************************* Public Sub MakeArrayText() Dim fs, ts 'オブジェクト取得用 Dim strCurDir As String 'カレントフォルダ名 Dim strTextName As String 'テキストファイル名 Dim strTextFile As String 'テキストファイルのフルパス名 Dim i As Long, j As Long 'ループ用 Dim x0 As Long, x1 As Long 'セル位置用 Dim y0 As Long, y1 As Long 'セル位置用 Dim nArrayM As Long '配列の1次元目の要素数 Dim nArrayN As Long '配列の2次元目の要素数 Dim strArrayName As String '配列の変数名 Dim strArrayType As String '配列の型名 Dim strDef1 As String '#defineの定義名 Dim strDef2 As String '#defineの定義名 Dim strTemp As String '汎用の文字列 'ワークブックのフォルダ名を取得 strCurDir = ThisWorkbook.Path 'ファイルオブジェクト生成 Set fs = CreateObject("Scripting.FileSystemObject") 'テキストファイル名の設定 strTextName = "array.txt" strTextFile = strCurDir & "\" & strTextName 'テキストファイルの作成(新規作成) On Error GoTo L_ERR1 Set ts = fs.CreateTextFile(strTextFile, True) On Error GoTo 0 'ワークシート上の設定値を取得 strArrayName = Range("B1").Text '配列の変数名 strArrayType = Range("B2").Text '配列の型名 nArrayM = Range("B3").Value '配列の1次元目の要素数 nArrayN = Range("B4").Value '配列の2次元目の要素数 'テキストファイルへコメント、#define定義、配列宣言部分などを書込み strDef1 = "MAX_M": strDef2 = "MAX_N" '#defineの定義名をセット strTemp = "/* The created array data. */" & vbCrLf ts.Write strTemp 'コメントの書込み strTemp = "#define " & strDef1 & " " & nArrayM & vbCrLf ts.Write strTemp '#defineの書込み strTemp = "#define " & strDef2 & " " & nArrayN & vbCrLf ts.Write strTemp '#defineの書込み strTemp = strArrayType & " " & strArrayName _ & "[" & strDef1 & "]" & "[" & strDef2 & "] = {" & vbCrLf ts.Write strTemp '配列の宣言部分の書込み 'テキストファイルへ配列のデータ定義部分を書込み '※ワークシート上のデータを取得してテキストファイルへ書込む y0 = 6: x0 = 2 'セルの基準位置をセット For i = 0 To nArrayM - 1 '配列の1次元目の要素数分ループ strTemp = vbTab & "{ " '1次元目のブロックの先頭 y1 = y0 + i 'セルの行位置をセット For j = 0 To nArrayN - 1 '配列の2次元目の要素数分ループ x1 = x0 + j 'セルのカラム位置をセット strTemp = strTemp & Cells(y1, x1).Value 'セルのデータを取得 If (j + 1) < nArrayN Then strTemp = strTemp & ", " 'データ区切り(末尾以外) Else strTemp = strTemp & " " 'データ区切り(末尾) End If Next j If (i + 1) < nArrayM Then strTemp = strTemp & "}," & vbCrLf '1次元目のブロック区切り(末尾以外) Else strTemp = strTemp & "}" & vbCrLf '1次元目のブロック区切り(末尾) End If ts.Write strTemp '1行分を書込み Next i strTemp = "};" + vbCrLf ts.Write strTemp '定義ブロックの終端を書込み 'テキストファイルのクローズ ts.Close 'オブジェクトの解放 Set ts = Nothing Set fs = Nothing '処理終了のメッセージを表示 strTemp = "テキストファイルを作成しました。" MsgBox (strTemp) Exit Sub L_ERR1: '== エラー処理 == Set ts = Nothing Set fs = Nothing strTemp = "ファイルオープンに失敗しました。" MsgBox (strTemp) End Sub ============================== ■作成されるテキストファイルの出力例 /* The created array data. */ #define MAX_M 20 #define MAX_N 15 unsigned long array[MAX_M][MAX_N] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115 }, { 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215 }, { 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315 }, { 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415 }, { 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515 }, { 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615 }, { 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715 }, { 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815 }, { 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915 }, { 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015 }, { 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115 }, { 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215 }, { 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315 }, { 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415 }, { 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515 }, { 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615 }, { 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715 }, { 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815 }, { 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915 } }; ※作成されるテキストは、そのまま、Cソース本体にインクルード(#include "~~") で組み込めるような形式にしています。
お礼
回答ありがとうございます。 今回は1次元配列だけでよかったのですが、 今後、2次元配列も必要になるかもしれないので、 そのときのために参考になりました。
- D-Matsu
- ベストアンサー率45% (1080/2394)
csvで吐いてincludeするとか。 行末の,は補ってやらないといけませんが。 int hoge[] = { #include "fuga.csv" }; Excelで書いたmatrixを配列にする程度の整形ならVBAでちょっと書けばできそうな気がしますが。
- prophetok
- ベストアンサー率44% (13/29)
可読性以云々以前に、要素数が多い場合は、外部ファイルに記述、読みこんでオブジェクトを作るのが普通じゃないですか? ハードコーディングだと、データが変わるたびにコンパイルが必要になりますよ。 エクセルのデータをCSV形式で出力して、読み込む、私ならそういう設計にしますけど。
補足
回答ありがとうございます。 普通のコンピュータの場合ならその方法を使うのですが、 相手はマイコンなので、ファイルの読み込みは使えません。 コンパイラもCSVから自動的に変数を作ったりはしてくれないようです。 説明不足で申し訳ございません。
- D-Matsu
- ベストアンサー率45% (1080/2394)
何も考えずにcsvで出力し、テキストエディタの置換機能を駆使して{},及びタブを埋め込む。 細かい部分は手で調整。 ……というのが一番手間いらずな気がします。
お礼
回答ありがとうございます。 まさしく求めていた機能が使えるようになりました。