マクロソースの説明


概要

ここでのマクロとは表次郎を任意の処理で動くように記述しておくと処理を呼び出すだけで
自動的に行うようにする機能です。

記述の雰囲気はC風にしています。
例としては下記のように条件文などは大括弧"{"、"}"で囲んだり、命令の最後にはセミコロン";"を記述します。
また、大文字と小文字は別ものと判断します。「int」と「Int」は別ものです。
変数定義やコメントなんかも//や/* */で記述するあたりも似た感じにしています。
ただし、記述できることはかなり少ないので注意ください。

int i;

// コメント
i = input("数値",1,"");
if(i == 5){
  cell(1,2) = "Hello World";
}

記述したソースを「表次郎」のメニュー「マクロ」-「マクロの登録」から「表次郎マクロ登録」画面から
ソースをコンパイルすることで「表次郎」のメニュー「マクロ」-「マクロの実行」またはショートカットの
[Ctl]+[M]からマクロ実行画面を表示して登録したマクロ名を選択して実行すると
ソースの内容に従った処理を実行します。





ソースの構成

   

@マクロ説明のコメント

必須の作業ではないですがソースの最初にマクロの説明文を記述します。
"//"の命令は記述後、行間でコメントとして判断するので自由に文章を記述できます。
マクロに対する内容など書いておくとどんな機能であったかを思い出すことが出来るので
記述することをおすすめします。

次にシステム的に意味しますが
先頭行から順に"//"で記述して"<処理説明>"というキーワードを見つけたら
該当行以降のコメントで"//"が切れた時点もしくは"//"のみの記述になるまでの文章を
表次郎マクロ登録の「ファイル選択」した時点で「処理説明」に文章を取り込みます。
編集モードがOFFのときはコンパイルボタン押下時にも読込ます。

A外部ファイル読込欄

指定したファイルのソースを読み込みます。
使用するファイルのパスは常に実行ファイルを入れたフォルダの「macro」フォルダに配置する
必要があります。
また、ソース上には記述しないですがファイルの拡張子は「.hsh」のもののみ読み込むことが出来ます。
※#includeの記述は必ず行の先頭から指定してください。

B変数定義欄

変数とは値を保持する領域ですが文字列を扱いたい場合は"string"、
整数を扱いたい場合は"int"といった風に領域を確保します。
記述方法は型の種類、文字列

C処理実行欄

プログラムを記述していきます。
記述した順番に表次郎を操作する命令を記述していきます。
命令については一覧を参考ください。


コメント

プログラムを見たとき内容を理解しやすくするための注釈です。
書き方は"//"の後ろに書く内容が行内でコメントとなります。
複数行をコメントにする場合は開始"/*"からコメントの最後は"*/"

string aaa;  // ここがコメント行です。

/*
  複数行の
コメントです。
*/

変数定義

変数はユーザーが値を任意に保持したりする領域です。
変数名は任意に入力出来ます。
・intなど既に定義されている名前は使用出来ません。
・数字のみの変数も使用出来ません。

string aaa;
int XXXX;
double bb;
date dt;

aaa = "Hello";
XXXX = 3;
bb = 3.5;
dt = "2021/01/31";


【変数定義一覧】

内容
string 文字列
int 整数
double 実数
date 日付
sheet 扱うシートを指定する場合に使用する。


【型の変換について】

型が異なるものも代入できるものについては自動で変換します。
ただし、数値の変換に文字列を入れるなど変換できないものについては
実行時にエラーとなります。

int a;
string txt;

txt = "123";
a = txt;
cell(1,1) = a;
>結果:123

txt = "ABC";
a = txt;   ←エラー



【小数点について】

数値を扱う際はint型とdouble型を使用しますがint型に
小数点を入れた場合は切り捨てられます。

int a;
a = 1.23;
cell(1,1) = a;
>結果:1  ← aは整数なので小数点部分は切り捨てられます

double b;
b = 1.23;
cell(1,1) = b;
>結果:1.23

b = 1 / 3;
cell(1,1) = b;
>結果:0 ← 計算時点で整数として判断される

b = 1.0 / 3;
cell(1,1) = b;
>結果:0.333333333333333 ← 1.0と入力でdobule扱いする

string s;
s = "1";
cell(1,1) = s / 3;
>結果:0.333333333333333

【シート型について】

シート型は他の変数と違った扱い方をします。
変数にシート名を指定して特定の関数の頭に
変数をピリオドで付けると該当の関数は指定したシート上のデータを扱う
ことが出来ます。
シートの指定がない場合は実行時にエラーとなります。
使用できる関数は一覧表の「SHEET指定」が「○」のものとなります。
指定しない場合は開いているシート上のデータを対象とします。

sheet st;

st = "Sheet1";  // シート名が「Sheet1」のシートを指定
st.cell(1,2) = "Hello";


【文字列について(改行文字の指定など)】

文字列型に値をセットする方法はダブルコーテーション、または
シングルコーテーションで囲んだ内容がデータとして扱われます。

データ内にダブルコーテーションまたはシングルコーテーションが
ある場合はダブルコーテーションで囲んでいる場合は
ダブルコーテーションを2つ並べて書くと1文字のダブルコーテーション
として扱います。

改行文字は"\n"で書きます。
"\\"を書くと"\"になります。

タブ文字は当処理では扱えません。

cell(1,1) = "Hello";  // ダブルコーテーションで囲んだ例
 ↓
Hello

-----------------------------------------
cell(1,1) = """あいう"""; // "あいう"をデータとする例
cell(1,1) = '"あいう"';   // "あいうをデータとする例2
 ↓
"あいう"

------------------------------------------
cell(1,1) = "Hello\n改行";  // セル内で\nは改行
 ↓
Hello
改行

-----------------------------------------
cell(1,1) = "\\n";  // \nを内容とする場合
 ↓
\n

----------------------------------------
cell(1,1) = "\\";   // \となる
 ↓
\



【グローバル変数・ローカル変数】

関数外の処理の最初に定義する変数をグローバル変数
関数内に定義を行うとローカル変数となります。
関数ごとに同じ名前の変数を定義しても別の値として扱ってくれます。

int 値;  // グローバル変数

値 = 10;

void test()
{
  int 値;  // ローカル変数

  値 = 15;
  cell(2,1) = 値;
}

cell(1,1) = 値;
test();
cell(3,1) = 値;  // ローカル変数の値は反映しない

--結果-----------------------
10
15
10


条件分岐(if()文)

if(条件式){
  命令;
} else {
  命令;
}

if()文の条件式が条件を満たす(true)場合は大括弧で囲った範囲内に記述した命令を実行します。
「条件以外」(false)の場合はelse文後の大括弧で囲った範囲に記述した命令を実行します。
elseの記述は任意です。

【条件式】

条件 内容
「a == b」または
「a = b」
aとbが一致するときはtrue、以外はfalse
「a <= b」 aとbが同じかaよりbが大きいときはtrue、以外はfalse
「a < b」 aよりbが大きいときはtrue、以外はfalse
「a >= b」 aとbが同じかaがbより大きいときはtrue、以外はfalse
「a > b」 aがbより大きいときはtrue、以外はfalse
「a <> b」または
「a != b」
aとbが一致しないときtrue、以外はfalse

【論理演算子】

    ・ORまたはANDの条件は5つまで指定可能
    ・ANDとORがある場合はANDを優先します。
意味 内容
「かつ」 「and」または「&&」
「または」 「or」または「||」

【注意事項】

 世間のプログラムに出来て表次郎に出来ないこと。
  ・ORまたはANDの条件は5つまで可能です。
  ・ANDとORではANDを優先します。
  ・条件内で()での優先度を変更することは出来ません。
  ・if()文やelseの後は命令が1つであっても必ず大括弧で囲んでください。

【ANDまたはORの書き方例】

int  a;

// ANDの例 aが1から9または30から39のとき実行する
a = 3;
if(a >= 1 and a <= 9 or a >= 30 and a <= 39){
  命令;
}

【ORを優先する書き方例】

int a, b;

// b=1かつaが1または10のとき実行する
// if(b == 1 and (a == 1 or a == 10)){
// のような書き方は出来ないので下記のandとorを
// 分ける必要がある。
a = 1;
b = 1;
if(b==1){
 if(a == 1 or a == 10){
   命令;
 }
}

【elseの後ろにifを並べる書き方例】

int flag;

flag = 0;
if(a == 1){
  flag = 1;
} else if(a == 3){
  flag = 1;
} else if(a == 4){
  flag = 1;
} else {
  flag = 2;
}
if(flag == 1{
  命令;
}

繰り返し処理(while()文)

while(条件式){
  命令;
}

while()文の条件式が条件を満たす(true)場合は大括弧で囲った範囲内に記述した命令を
条件以外になるまで実行を繰り返します。
条件式はif()文と同じです。
また、while()の命令の中にbreak;を記述するとループを抜けます。

【注意事項】

 世間のプログラムに出来て表次郎に出来ないこと。
  ・ANDやORで条件をつなげることは出来ません。
  ・for()文はないのでwhile()文を使用してください。
  ・無限ループにならないように注意ください。
   表次郎では特定の処理回数を超えたら警告が発生します。
   

【全ての行データを読み込む書き方例】

int row, max;
max = get_row_max();
row = 1;
while(row <= max){
  命令;
  row = row + 1;
}

while(row <= get_row_max())という記述は可能ですが
命令の中にセルを更新する処理があり常に最大行数がUPする
ような処理の場合は無限ループになるのでサンプルのように
変数に最大数を取得してあるほうを推奨します。

【全てのセルを読み込む書き方例】

int row, row_max;
int col, col_max;
col_max = get_col_max();
row_max = get_row_max();
row = 1;
while(row <= row_max){
  col = 1;
  while(col <= col_max){
    命令;
    col = col + 1;
  }
  row = row + 1;
}


【処理の途中で抜ける書き方例】

int row;
row = 1;
while(row <= 10)
{
  if(条件){
    break;  ←条件に一致したらループを抜ける
  }
  命令;
  row = row + 1;
}



演算式

int a;
double b, c;
a = 1 + 2;
cell(1,1) = a;  ← 3
b = 10 / 3;
cell(2,1) = b;  ← 3(注意:10が整数なので整数と判断される)
b = 10.0 / 3;
cell(3,1) = b;  ← 3.33333333333333
c = 10;
b = c / 3;
cell(4,1) = b;  ← 3.33333333333333
a = 1 + 2 + 3;  ← 6
cell(5,1) = a;
a = 4 * 5 + 3 * 2;
cell(6,1) = a;  ← 26
a = 4 * (5 + 3);
cell(7,1) = a;  ← 32
a = cell(3,4);  ←3行目、4列目が空の場合はaは0扱い


【演算式】

記号 内容
+ 加算
- 減算
* 乗算
/ 除算(0で割ると0扱いされます。ただし今後エラーにするかも?)
% 余り(0で割ると0扱いされます。ただし今後エラーにするかも?)


例にあるように一般的な四則演算が可能です。
乗算、除算が優先が高く加算、減算でも括弧で囲むことで優先順位を
上げることが可能です。

ただし、型により小数点の扱い方には注意ください。


関数の指定例

string test(int row, int col)  // <= 関数
{
  int str;
  str = cell(row, col);
  str = union("""", str, """");
  return str;
}

// 関数の呼び出し
msg(test(5,6));   // 5行目、6列目のセルの内容に
                  // ダブルコーテーションを囲んで
                  // メッセージを表示する

【関数の指定方法】
   以下の4つの処理で構成された命令が関数となり、以降の処理で呼び出す
  ことが可能です。
   ・戻り値の変数定義 : 関数の戻り値の変数を定義します。
                  値を返さない場合はvoidを指定します。
                  sheetの指定は出来ません。
   ・関数名 : 
   ・"(" 引数 ")"
   ・以降大括弧で囲んだ処理

【備考】
 ・呼び出すより前に関数を記述(C言語的だがプロトタイプ宣言はありません。)
 ・引数の値は常に値渡しとなるのでレスポンスを求めるならグローバル変数的で値を渡すほうが良い。

#includeについて

#include "calender"

// calender.hshファイルに記述された関数を呼び出す
listSyuku("2021", get_cur_row(), get_cur_col());


【内容】
  よく使う関数をマクロごとにコピーして利用するのは対象の関数に修正が発生したとき
  コピーしたファイル全てに対して修正を入れる必要があるのでメンテナンスの観点
  で良くありません。
  そこでインクルードファイルに関数を用意しておけば修正するファイルは
  1つで全ての処理に修正内容が反映されます。

  注意点としてはincludeファイルから呼び出された関数の中でエラーが発生したとき
  エラーの行番号はincludeファイルを呼び出した行になるため
  エラーに対するメンテナンスは難しくなるのでエラーが出なくなってから
  includeファイルで扱うことをおすすめします。


【#includeの指定方法】
  #includeの命令の後にファイル名を指定します。
  ・ファイル名の前後にダブルコーテーションで囲む必要があります。
  ・ファイルはソースファイルと同じフォルダにあるファイルを参照します。(ver4.0以降)
   ファイルが見つからない場合は実行ファイルを置いたフォルダのmacroフォルダにある
   ファイルを参照します。
  ・拡張子を指定しない場合は「.hsh」となります。
  ・ファイル名は30文字まで。
  ・#includeの指定は他の命令とは違ってスペースを空けずに左に詰めて記述してください。
  ・命令の最後にセミコロンは不要です。
  ・includeファイルの中に#includeの指定は出来ません。



配列について

厳密には配列は存在しません。
代わりに配列的に扱う関数を用意しています。
整数型を扱うarray(index)、文字列型を扱うarray_str(index)です。
配列とは違いますがarray_word()というプログラム的な意味での単語単位を作者の
独自の解釈をもとに分類して配列的に扱うようにしたものを用意しています。

使用する前に領域を確保する必要があります。
create_array(100);とするとarray(0)からarray(99)までの配列が使用可能となります。
array_str()も同様にcreate_array_str(100)でarray_str(0)からarray_str(99)までに
文字列が設定出来ます。

array_str()はarray()と違って第2引数にAS0(0)からAS4(4)を指定することで
複数のarray_str()を使用することができるようになります。第2引数を省略するとAS0(0)と
同じ意味となります。

第2引数に指定するAS0〜AS4は0〜4の定数で数字を指定してもいいですが
数字だと2次元配列のように見えるのでここではAS0とかの定数を使用する
ようにします。

【整数を扱う配列】

// 整数の扱い方
int nLp;

create_array(100);
nLp = 0;
while(nLp < 100)
{
  // array()を使う意味は無いですが使い方
  array(nLp) = nLp;
  cell(nLp + 1,1) = array(nLp);
  nLp = nLp + 1;
}

-- 結果 ----------------------
0
1
2
:
98
99

【文字列を扱う配列】

int nRow;

create_array_str(10);
array_str(0) = "りんご";
array_str(1) = "みかん";
array_str(2) = "柿";
nRow = 1;
while(nRow < 100)
{
  cell(nRow,1) = array_str(get_random(3));
  nRow = nRow + 1;
}

-- 結果(ランダムなので何が配置されるかは変わります)----
柿
みかん
みかん
りんご
柿
りんご
 :
みかん



【文字列を扱う配列を複数扱う例】

int nIndex;

create_array_str(10, AS0);
array_str(0, AS0) = "りんご";
array_str(1, AS0) = "みかん";
array_str(2, AS0) = "柿";

create_array_str(10, AS1);
array_str(0, AS1) = "\200円";
array_str(1, AS1) = "\500円";
array_str(2, AS1) = "\300円";

nIndex = select_array_str("果物", "選択下さい。",AS0);
if(nIndex < 0){
    quit();
}
cell(1,1) = array_str(nIndex, AS1);

-- 結果 ---------------------------
選択画面が出て「柿」を選択すると
1行目の1列目に「\300円」を設定