Excelデータから、「変数名」と「ブロックタイプ」を読み取り、それに応じた Simulinkブロックを生成
仕様
- Excelファイルに「データストア名」と「ブロックタイプ(Read または Write)」を記載
- 記載されたブロックタイプに応じて、DataStoreWrite または DataStoreRead ブロックを生成
- 生成されたブロックを縦並びで配置(ReadブロックとWriteブロックは別の列で生成)
Excelファイルの形式
- ファイル名: “
generate_simulink_blocks
“.xlsx
※任意の名称でOK - シート名:
Sheet1
←ここは変更しない様に! - 列構成:
A列
: 変数名B列
: ブロックタイプ(Read
またはWrite
)
※値の入力は、3行目から!!(1行目はヘッダー、2行目は空白)
変数名 | データタイプ | |
DataStoreRead_Block01 | Read | |
DataStoreWrite_Block01 | Write | |
Goto_Block01 | Goto | |
From_Block01 | From | |
Inport_Block01 | Inport | |
Outport_Block | Outport |
MATLABスクリプト
MATLABのホームウィンドウから、「新規スクリプト」を作成し、下記のコードをコピペ
- 6種のブロックに対応
- DataStoreブロックのみ対応
function generate_simulink_blocks(filename, modelName)
% generate_simulink_blocks
% Excelファイルに基づいてSimulinkモデルに指定されたブロックを自動生成します。
%
% 使用方法:
% generate_simulink_blocks('blocks.xlsx', 'your_model_name')
%
% 引数:
% filename - ブロック情報を記載したExcelファイル
% modelName - 操作対象のSimulinkモデル名
% ------------------------
% 設定
% ------------------------
% ブロックサイズ設定
BLOCK_WIDTH = 250; % ブロックの幅
BLOCK_HEIGHT = 30; % ブロックの高さ
% 基準座標の設定
positions = struct(...
'Inport', [100, 100], ...
'Outport', [700, 100], ...
'Goto', [300, 100], ...
'From', [500, 100], ...
'Read', [100, 400], ...
'Write', [500, 400] ...
);
yOffset = 35; % 縦方向の間隔
% ------------------------
% Excelファイルからデータを読み込む
% ------------------------
data = readtable(filename, 'Sheet', 'Sheet1', 'ReadRowNames', false);
% ヘッダー行をスキップして2行目以降のデータを取得
data = data(2:end, :);
% 空白行や欠損値を削除
data = data(~any(ismissing(data), 2), :);
% Simulinkモデルを開く
load_system(modelName);
% ------------------------
% ブロック生成
% ------------------------
blockCounts = struct('Inport', 0, 'Outport', 0, 'Goto', 0, 'From', 0, 'Read', 0, 'Write', 0);
for i = 1:height(data)
% 変数名とブロックタイプを取得
blockName = data{i, 1}{1}; % 変数名称
blockType = data{i, 2}{1}; % ブロックタイプ
% 空白セルや不正なデータをスキップ
if isempty(blockName) || isempty(blockType)
continue;
end
% ブロックの基準座標とカウンタを取得
if isfield(positions, blockType)
basePosition = positions.(blockType);
count = blockCounts.(blockType);
position = [
basePosition(1), ...
basePosition(2) + count * yOffset, ...
basePosition(1) + BLOCK_WIDTH, ...
basePosition(2) + count * yOffset + BLOCK_HEIGHT
];
% ブロック生成
switch blockType
case 'Inport'
add_block('simulink/Sources/In1', ...
sprintf('%s/%s', modelName, blockName), ...
'Position', position, ...
'ShowName', 'on', ... % ブロック名を表示
'Port', num2str(count + 1)); % ポート番号を設定
case 'Outport'
add_block('simulink/Sinks/Out1', ...
sprintf('%s/%s', modelName, blockName), ...
'Position', position, ...
'ShowName', 'on', ... % ブロック名を表示
'Port', num2str(count + 1)); % ポート番号を設定
case 'Goto'
add_block('simulink/Signal Routing/Goto', ...
sprintf('%s/Goto_%d', modelName, count + 1), ...
'Position', position, ...
'GotoTag', blockName, ...
'ShowName', 'off');
case 'From'
add_block('simulink/Signal Routing/From', ...
sprintf('%s/From_%d', modelName, count + 1), ...
'Position', position, ...
'GotoTag', blockName, ...
'ShowName', 'off');
case 'Read'
add_block('simulink/Signal Routing/Data Store Read', ...
sprintf('%s/DataStoreRead_%d', modelName, count + 1), ...
'Position', position, ...
'DataStoreName', blockName, ...
'ShowName', 'off');
case 'Write'
add_block('simulink/Signal Routing/Data Store Write', ...
sprintf('%s/DataStoreWrite_%d', modelName, count + 1), ...
'Position', position, ...
'DataStoreName', blockName, ...
'ShowName', 'off');
otherwise
warning('不明なブロックタイプ: %s (行 %d)', blockType, i);
end
% カウンタを更新
blockCounts.(blockType) = blockCounts.(blockType) + 1;
else
warning('無効なブロックタイプ: %s', blockType);
end
end
% ------------------------
% モデルを保存
% ------------------------
save_system(modelName);
% ------------------------
% 総数とタイプ別の数を表示
% ------------------------
totalCount = sum(struct2array(blockCounts)); % 総数
fprintf('------------------------\n');
fprintf('生成されたデータの総数\n');
fprintf('総数: %4d\n', totalCount);
fields = fieldnames(blockCounts);
for k = 1:numel(fields)
fprintf('%s ブロック数: %4d\n', fields{k}, blockCounts.(fields{k}));
end
fprintf('ブロックの生成が完了しました!\n');
end
function generate_simulink_blocks(filename, modelName)
% generate_simulink_blocks
% Excelファイルに基づいてSimulinkモデルにDataStoreWriteおよび
% DataStoreReadブロックを自動生成します。
%
% 使用方法:
% generate_simulink_blocks('datastore_blocks.xlsx', 'your_model_name')
%
% 引数:
% filename - データストア情報を記載したExcelファイル
% modelName - 操作対象のSimulinkモデル名
% ------------------------
% 設定
% ------------------------
% ブロックサイズ設定
BLOCK_WIDTH = 250; % ブロックの幅
BLOCK_HEIGHT = 30; % ブロックの高さ
% 基準座標の設定
readBasePosition = [100, 100]; % Readブロックの基準位置 (x, y)
writeBasePosition = [500, 100]; % Writeブロックの基準位置 (x, y)
yOffset = 35; % 縦方向の間隔 (変更)
% ------------------------
% Excelファイルからデータを読み込む
% ------------------------
data = readtable(filename, 'Sheet', 'Sheet1', 'ReadRowNames', false);
% ヘッダー行をスキップして2行目以降のデータを取得
data = data(2:end, :);
% 空白行や欠損値を削除
data = data(~any(ismissing(data), 2), :);
% Simulinkモデルを開く
load_system(modelName);
% ------------------------
% ブロック生成
% ------------------------
writeCount = 0; % Writeブロックの数
readCount = 0; % Readブロックの数
for i = 1:height(data)
% データストア名とブロックタイプを取得
datastoreName = data{i, 1}{1}; % データストア名
blockType = data{i, 2}{1}; % ブロックタイプ (Read or Write)
% 空白セルや不正なデータをスキップ
if isempty(datastoreName) || isempty(blockType)
continue;
end
% Readブロックを先に生成
if strcmp(blockType, 'Read')
position = [
readBasePosition(1), ...
readBasePosition(2) + readCount * yOffset, ...
readBasePosition(1) + BLOCK_WIDTH, ...
readBasePosition(2) + readCount * yOffset + BLOCK_HEIGHT
];
blockName = sprintf('%s/DataStoreRead_%d', modelName, readCount + 1);
add_block('simulink/Signal Routing/Data Store Read', blockName, ...
'Position', position, ...
'DataStoreName', datastoreName, ...
'ShowName', 'off'); % ブロック名を非表示
readCount = readCount + 1; % Readカウンタを更新
% 次にWriteブロックを生成
elseif strcmp(blockType, 'Write')
position = [
writeBasePosition(1), ...
writeBasePosition(2) + writeCount * yOffset, ...
writeBasePosition(1) + BLOCK_WIDTH, ...
writeBasePosition(2) + writeCount * yOffset + BLOCK_HEIGHT
];
blockName = sprintf('%s/DataStoreWrite_%d', modelName, writeCount + 1);
add_block('simulink/Signal Routing/Data Store Write', blockName, ...
'Position', position, ...
'DataStoreName', datastoreName, ...
'ShowName', 'off'); % ブロック名を非表示
writeCount = writeCount + 1; % Writeカウンタを更新
else
warning('不明なブロックタイプ: %s (行 %d)', blockType, i);
end
end
% ------------------------
% モデルを保存
% ------------------------
save_system(modelName);
% 総数とデータタイプごとの数を表示
totalCount = writeCount + readCount; % 総数
% 4桁で表示
fprintf('------------------------\n');
fprintf('生成されたデータの数\n');
fprintf('総数: %4d\n', totalCount); % 4桁表示
fprintf('DataStoreRead ブロック数: %4d\n', readCount); % 4桁表示
fprintf('DataStoreWrite ブロック数: %4d\n', writeCount); % 4桁表示
fprintf('ブロックの生成が完了しました!\n');
end
使用方法
スクリプトを保存
- 上記のコードを
generate_datastore_blocks.m
という名前で保存します - 保存先は、MATLABの作業ディレクトリにしてください
※それ以外でも問題ないが、わかりにくくなるため
Simulinkモデルを準備
- モデルを作成または既存モデルを準備します
- 例:
my_model.slx
として保存
※良きせぬバグを防ぐため、新規モデルを作成し、そこに生成されたブロックをコピペで使用すること!
Excelファイルを準備
- 仕様どおりにExcelファイル(例:
datastore_blocks.xlsx
)を作成し、データストア名とブロックタイプを記載します
スクリプトを実行
- MATLABコマンドウィンドウで以下を入力します
※'datastore_blocks.xlsx
‘と'my_model
‘は適宜変更してください
generate_datastore_blocks('datastore_blocks.xlsx', 'my_model');
結果を確認
- コマンドウィンドウに生成されたデータの総数が表示され、エラーがないか確認
- 指定したSimulinkモデルを開き、ブロックが生成されていることを確認
スクリプトの説明
- Excelデータの読み込み
readtable
を使用してExcelファイルを読み込み、データストア名とブロックタイプを取得- 値の入力は、3行目から!!(1行目はヘッダー、2行目は空白)
- 座標計算
writeBasePosition
とreadBasePosition
を基準に、yOffset
を加算して縦方向に並べる- WriteブロックとReadブロックは別々の列に配置
- ブロックの生成
- ブロックタイプに応じて
add_block
を使用し、適切なブロックを追加 - ブロックのパラメータとして
DataStoreName
を設定
- ブロックタイプに応じて
- エラー処理
- 不明なブロックタイプ(
Read
またはWrite
以外)は警告を表示
- 不明なブロックタイプ(
注意点
- モデルの保存前にバックアップを取ることをお勧めします
- Excelの列やシート名が異なる場合はコードを調整してください
your_model_name
を実際のモデル名に置き換えてください
動作確認済 バージョン
- MATLAB Simulink 2018b(9.5.0.1586782)64-bit