ExcelでVBAを使うまで。-Excelでマクロを使えるようにする-
VBAを使うまで
簡単な環境設定みたいなものです。
まず、Excelを開いてください。
「ファイル」から「オプション」を選んで
「リボンのユーザー設定」から「開発]にチェックを
これで、Excelに開発タブが増え、表示にマクロができます。
このマクロで、記録する機能を使うだけでも十分違いますので、今回その説明も加えて。
例えばシート内の全ての文字を消したい場合
これで、マクロの記録をします。全消しの場合は全て選んでDeleteを押せばいいだけなので、それをMacro1として保存します。
終わったら記録終了を押しましょう。
これで、Macro1は全て消す操作になります。
この実行方法ですが
この「開発」タブの挿入からボタンのようなものを選ぶことで、図の中のボタンのようなものが作れます。この時、マクロを選ぶ画面がでますので、そこで選べばいいだけです。
実行するときはクリックするだけ。
C++ クラスの復習。オブジェクト指向っぽく
クラスの復習
今回はUserクラスという物を作成し、名前と点数を持たせます。
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) using namespace std; class User{ private: string name; int score; int rank; public: User() { name = "none"; score = 0; } User(string st) { name = st; score = 0; } User(string st,int a) { name = st; score = a; } void setscore(int a) { score = a; } int getscore() { return score; } string getname() { return name; } };
クラスの最後に;を忘れないように
ここでは、Userクラスの宣言とともに初期化を行う、コンストラクタを定義しています。
コンストラクタはvoidなどの返り値の型を宣言する必要が無いので気を付けてください。(宣言したらビルドエラーでした)
この部分
User() { name = "none"; score = 0; } User(string st) { name = st; score = 0; } User(string st,int a) { name = st; score = a; }
これで初期化して、名前と点数を呼び出してみようと思います。
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) using namespace std; class User{ private: string name; int score; int rank; public: User() { name = "none"; score = 0; } User(string st) { name = st; score = 0; } User(string st,int a) { name = st; score = a; } void setscore(int a) { score = a; } int getscore() { return score; } string getname() { return name; } }; int main() { User a("taro",60); cout<<"name:"<<a.getname()<<" score:"<<a.getscore()<<endl; return 0; }
実行結果
こんな感じです。名前のみの場合
と点数が0になっているのが分かるかと思います。
(欠席した場合、0点的な・・・)
複数人にした場合
int main() { User taro("taro",60); User hanako("hanako",90); User takeshi("takeshi",30); User jiro("jiro",100); cout<<"name:"<<taro.getname()<<" score:"<<taro.getscore()<<endl; cout<<"name:"<<hanako.getname()<<" score:"<<hanako.getscore()<<endl; cout<<"name:"<<takeshi.getname()<<" score:"<<takeshi.getscore()<<endl; cout<<"name:"<<jiro.getname()<<" score:"<<jiro.getscore()<<endl; return 0; }
と変更すれば、人数は増えますが・・・
ということで配列に変更することに。
その場合、set出来る関数があったほうが楽なので作成
void set(string st, int a) { name = st; score = a; }
int main() { User user[4]; user[0].set("taro",60); user[1].set("hanako",90); user[2].set("takeshi",40); user[3].set("jiro",100); for (int i = 0; i < ARRAY_LENGTH(user); i++) { cout<<"name:"<<user[i].getname()<<" score:"<<user[i].getscore()<<endl; } return 0; }
これで
いい感じですね。
今日はここまでで
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) using namespace std; class User{ private: string name; int score; int rank; public: User() { name = "none"; score = 0; } User(string st) { name = st; score = 0; } User(string st,int a) { name = st; score = a; } void setscore(int a) { score = a; } void set(string st, int a) { name = st; score = a; } int getscore() { return score; } string getname() { return name; } }; int main() { User user[4]; user[0].set("taro",60); user[1].set("hanako",90); user[2].set("takeshi",40); user[3].set("jiro",100); for (int i = 0; i < ARRAY_LENGTH(user); i++) { cout<<"name:"<<user[i].getname()<<" score:"<<user[i].getscore()<<endl; } return 0; }
C++ クラスと関数の扱い。public と private
今、練習中に気づきましたが
C++でarrayで安易にsizeofを使おうとすると大変なことになりますね。
int a[5]; for(int i = 0; i < sizeof(a);i++){ cout<<a[i]<<endl; }
とかやろうとすると、上手くいかないんですね。
こういうときは
sizeof(array) / sizeof(array[0])
を使うようですね。
実際
#include<iostream> #include<string> using namespace std; int main() { int a[5] = { 0,0,0,0,0 }; cout << sizeof(a) << endl; return 0; }
とすると
20らしいです。
sizeof(array) / sizeof(array[0])
を使うと
となっていい感じです。
これはもう定義しておきましょう。
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) using namespace std; int main() { int a[5] = { 0,0,0,0,0 }; cout << ARRAY_LENGTH(a) << endl; return 0; }
クラスと関数
クラスの作り方ですが、すごく適当に言えばこんな感じ。
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) #define NUM 5 using namespace std; class Stack{ public: int value = rand() % 100 + 1; }; int main() { Stack a; Stack b; return 0; }
{}を閉じるタイミングがすごく慣れないです。
これでStackクラスが出来ました。したのint main()の所でStackクラスの変数を2つ宣言しています。
このaとbはvalueの値を持っているので、ピリオドで繋ぐことで使うことが出来ます。出力してみると
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) #define NUM 5 using namespace std; class Stack{ public: int value = rand() % 100 + 1; }; int main() { Stack a; Stack b; cout << "a=" << a.value << endl; cout << "b=" << b.value << endl; return 0; }
いい感じですね。
ここでpublicとprivateの差に入ります
publicとprivate
とりあえず、public→privateへ変換
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) #define NUM 5 using namespace std; class Stack{ private: int value = rand() % 100 + 1; }; int main() { Stack a; Stack b; cout << "a=" << a.value << endl; cout << "b=" << b.value << endl; return 0; }
これで実行しようとするとビルドエラー
こんなエラーが出ています
エラー C2248 'Stack::value': private メンバー (クラス 'Stack' で宣言されている) にアクセスできません。
要は、privateにするとStackクラス内からしか操作できなくなります。もちろん出力だけも禁止です。今回エラーの原因は15,16行目ですね。
なので、出力する関数をStackクラス内に書きます。
class Stack{ private: int value = rand() % 100 + 1; public: int getvalue(); }; int Stack::getvalue() { return value; }
といって取得する関数でもいいですし
class Stack{ private: int value = rand() % 100 + 1; public: void getvalue(); }; void Stack::getvalue() { cout<<value<<endl; }
でもいいです。
ここで、クラス内でちゃんと返り値などの定義もしてあげないと動かないので(これが分かるのに時間かかった・・・)注意してください。
set等も同様に行うことで、関数を経由しないと数値が操作できなくなります。勝手に値を変えられないように制限するために使ったりするのかな?
#include<iostream> #include<string> #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) #define NUM 5 using namespace std; class Stack{ private: int value; public: int getvalue(); void setvalue(); }; int Stack::getvalue() { return value; } void Stack::setvalue() { cin >> value; } int main() { Stack a; Stack b; a.setvalue(); b.setvalue(); cout << "a=" << a.getvalue() << endl; cout << "b=" << b.getvalue() << endl; return 0; }
C++ 複数入力。defineの使い方からバブルソートとセレクションソートなどの並び替え
バブルソート
複数入力をするとどうなるのか
要はこれです。どうなるのか
int main() { string a; int b; cin >> a >> b; cout << a << endl; cout << b << endl; return 0; }
実行結果
普通にEnterを押して複数個入力できるようです。
意外と楽ですね。
ソート人数の設定
一つの方法として#defineを使って最初に人数を定義しておく。
こんな感じ
#include<iostream> #include<string> #define NUM 5 using namespace std; int main() { return 0; }
こうすることでNUMが5という値になります。データの数を先に決めておく的な。
実行結果出すまでもないので・・・
最初にNUMをすることで、この後のプログラムを書く際にNUMの定義を変えれば人数を変えれることになります。柔軟になるということですね。
とりあえずこのままバブルソートへ
まずはNUM回の入力から。名前も入れましょうか。
#include<iostream> #include<string> #define NUM 5 using namespace std; int main() { string name[NUM]; int score[NUM]; for (int i = 0; i < NUM; i++) { cout << i + 1 << "人目の名前を入力してください" << endl; cin >> name[i]; cout << i + 1 << "人目の点数を入力してください" << endl; cin >>score[i]; } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" << name[i] << " " << score[i] << endl; } return 0; }
実行結果
上手くいっていますね。
今回のソートは昇順で流していくことにしましょう。昇順ができれば降順に変える方法は簡単なので。
同時に最大・最小も出力しましょう。
以上纏めると今回やることは
- バブルソートを行い、昇順にする
- 最高点の名前・点数を出力
- 最低点の名前・点数を出力
ではまず、バブルソートから
#include<iostream> #include<string> #define NUM 5 using namespace std; int main() { string name[NUM]; int score[NUM]; for (int i = 0; i < NUM; i++) { cout << i + 1 << "人目の名前と点数を入力してください" << endl; cin >> name[i]; cin >>score[i]; } for (int i = 0; i < NUM; i++) { for (int j = NUM - 1; j > i; j--) { if (score[j-1]>score[j]) { int a = score[j - 1]; score[j - 1] = score[j]; score[j] = a; string b = name[j - 1]; name[j - 1] = name[j]; name[j] = b; } } } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" << name[i] << " " << score[i] << endl; } return 0; }
実行結果
上手くいっていますね。
次は最大最小です。
といっても簡単で、これは最大・最小が更新されるたびにその[i]の値を残しておけばいいでしょう。
int型でmaxindexとminindexを宣言します。初期値を0にすることで、データが1個の時の最大値・最小値は1人目の点数になります。
#include<iostream> #include<string> #define NUM 5 using namespace std; int main() { string name[NUM]; int score[NUM]; int maxindex = 0; int minindex = 0; for (int i = 0; i < NUM; i++) { cout << i + 1 << "人目の名前と点数を入力してください" << endl; cin >> name[i]; cin >>score[i]; if (score[i] > score[maxindex]) { maxindex = i; } if (score[i] < score[minindex]) { minindex = i; } } cout << "最高点は" << name[maxindex] << " " << score[maxindex]<<endl; cout << "最低点は" << name[minindex] << " " << score[minindex]<<endl; for (int i = 0; i < NUM; i++) { for (int j = NUM - 1; j > i; j--) { if (score[j-1]>score[j]) { int a = score[j - 1]; score[j - 1] = score[j]; score[j] = a; string b = name[j - 1]; name[j - 1] = name[j]; name[j] = b; } } } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" << name[i] << " " << score[i] << endl; } return 0; }
実行結果
上手くいっていますね
乱数を使ってデータを入力する。
なんだか、AさんとかBさんとか毎回入力するのもバカバカしくなってきたので、ここも自動でやってもらいます。
C++にforeachのような構文があるのかよくわからないので、ここは配列を普通に使用してrandを使えば勝手に名前と点数を入れてくれるかな。
#include<iostream> #include<string> #define NUM 5 using namespace std; int main() { string name[NUM] = { "A","B","C","D","E" }; int score[NUM]; int maxindex = 0; int minindex = 0; for (int i = 0; i < NUM; i++) { cout << name[i] << "さんの点数:"; score[i] = (rand() % 100) + 1; cout << score[i] << endl; if (score[i] > score[maxindex]) { maxindex = i; } if (score[i] < score[minindex]) { minindex = i; } } cout << "最高点は" << name[maxindex] << " " << score[maxindex]<<endl; cout << "最低点は" << name[minindex] << " " << score[minindex]<<endl; for (int i = 0; i < NUM; i++) { for (int j = NUM - 1; j > i; j--) { if (score[j-1]>score[j]) { int a = score[j - 1]; score[j - 1] = score[j]; score[j] = a; string b = name[j - 1]; name[j - 1] = name[j]; name[j] = b; } } } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" << name[i] << " " << score[i] << endl; } return 0; }
実行結果
随分と楽になりました。
ここから先は名前とかどうでもいい(大学などで課題で出る場合は必要なのでしょうが)ので、点数のみでソートをかけることにしましょう。コードも少し長くなって見づらくなってきたので。
NUM 10に変更し
nameを消しました。
#include<iostream> #include<string> #define NUM 10 using namespace std; int main() { int score[NUM]; for (int i = 0; i < NUM; i++) { score[i] = (rand() % 100) + 1; cout<< i+1 <<":"<< score[i] << endl; } cout << endl; for (int i = 0; i < NUM; i++) { for (int j = NUM - 1; j > i; j--) { if (score[j-1]>score[j]) { int a = score[j - 1]; score[j - 1] = score[j]; score[j] = a; } } } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" <<score[i] << endl; } return 0; }
実行結果
いい感じですね。
それではセレクションソートへ。
セレクションソート
これは、最小(又は最大)の選び出し、昇順ならば一番上に吹っ飛ばし、次は一番上以外の数字の中で最小の数を探し、二番目にぶっ飛ばすソートです。
先ほどと同様、minindexを導入しましょう。
内部ループ(jのループ)では直接のデータ交換は無しです。あくまで最小の値を持つindexを保存するだけです。
外部ループ(iのループ)でデータを交換してください。
#include<iostream> #include<string> #define NUM 10 using namespace std; int main() { int score[NUM]; int minindex; for (int i = 0; i < NUM; i++) { score[i] = (rand() % 100) + 1; cout<< i+1 <<":"<< score[i] << endl; } cout << endl; for (int i = 0; i < NUM; i++) { minindex = i; //初期化 for (int j = i; j < NUM; j++) { if (score[minindex] > score[j]) { minindex = j; } } int a = score[i]; score[i] = score[minindex]; score[minindex] = a; } for (int i = 0; i < NUM; i++) { cout << i + 1 << ":" <<score[i] << endl; } return 0; }
実行結果
と、セレクションソートでした。
次はNUMの値を任意に変えても繰り返せるようになりたいですね。
C++ 入力と出力。簡単な演算まで
昨日、開発環境を整えたので今日は入力と出力から
入力と出力
出力は昨日もやってしまったのだが、cout>>を使うらしい
入力はcin<<らしい
なんて読むのかはよくわからない
cout>>"出力対象">>endl; //出力 cin<<"キーボードからの入力対象のオブジェクト"; //入力
実際にやってみると
#include<iostream> #include<string> using namespace std; int main() { string input; cout << "文字列を入力してください。"<<endl; cin >> input; cout << input << "と入力されました。" << endl; return 0; }
実行結果
そこそこ上手くいったかな?
ところで、昨日からstring型を使っているのだけど
char型でポインタを使う方法をあるらしい。
こんな感じ
char* ch = "hello";
どっちの方が普通かはわからないけど、stringは別で#includeが必要になるからなあ
とりあえず、同じ方法でinputが受け付けられるかやってみたら、エラーが出たので
この方法で文字列リテラルを受け付けるのは厳しいのかな?
同じようにint型の入力も試してみる
#include<iostream> #include<string> using namespace std; int main() { int a, b; cout << "a-->" << endl;cin >> a; cout << "b-->" << endl;cin >> b; cout << "a+b=" << a + b << endl; return 0; }
実行結果
上手くいってるよう。
ちなみに、int型にstring型を渡すと
と挙動不審になったけど動いた。
この動くのは怖いですね・・・
ついでにint型の配列の入力と出力もやってみた
#include<iostream> #include<string> using namespace std; int main() { int a[5]; for (int i = 0; i < 5; i++) { cin >> a[i]; } for (int i = 0; i < 5; i++) { cout << a[i] << endl; } return 0; }
実行結果
エラー出て簡単にしまくったけど
Javaみたいに変数nを読み込んでn個の配列は生成できないのかな?
それとArrays.toString()のような簡単に配列を出力する方法も調べたいな。
C++を初めてやる人へ。開発環境の導入(準備)から、出力まで。
なんか、元々Visual studioが入っていて中途半端な段階から進んだので、かなり時間がかかってしまいました。
やはり、開発環境の導入は最初の難関ですね・・・
Visual Studio のダウンロード
とりあえず、どれだけ調べてもVisual C++へと言われる感じしたので
ここからVisual Studio Communityをダウンロードしてインストール
そのままMicrosoftアカウントなどを入れて起動すると
なんかEclipseのような画面へ・・・
「ちょっと近づいたな・・・?」
という感覚。
Visual C++ (のパッケージなど)をインストール
左上の「ファイル」→「新規作成」から
プロジェクトを作成して
Visual C++を選択!
もういけるのか!!
と思いきや・・・
またこれだ・・・
長いな・・・おい・・・
やっとこさ
これも終わってプロジェクト作成
「なんとなく、間違っている気しかしない・・・」
と独り言を言っていました笑
初めての出力まで
なんかごちゃごちゃやってたらこんなことに・・・
わけがわからない。なんか既にほとんどできているテンプレートを使用してしまった?
とりあえず、気を取り直して
これか?
これも違った(30分くらい迷いましたが)
どうもこれらしい。
空のプロジェクトにチェックを付ける
これで、出てきた画面で
右のほうにあるソースファイルってところで右クリック
追加で項目を追加?
とりあえずそれでC++フォルダを作成できた。
そこで以下のプログラムを打ってデバッグ
#include<iostream> using namespace std; int main() { cout << "hello world" << endl; }
うお!?
一瞬(0.2秒くらい)hello worldが映った。
見えるかこんなの・・・
とりあえず、いろいろ参考にしてダメもとでreturn 0;も追加
今のプログラムはこんな感じ
Source.cpp
#include<iostream> using namespace std; int main() { cout << "hello world" << endl; return 0; }
で、これを押すらしい
すると
おおー。
いい感じですね。
とりあえず、導入は達成したのか?
出力もできたのか?
いっそのこと変数も使えるかと思って
#include<iostream> #include<string> using namespace std; int main() { string hello = "hello world"; string name = "name"; cout << name <<"さんから"<< hello<< endl; return 0; }
へ修正
すると
とりあえず今日のところは合格点ですね。
てこずりましたが、これからも頑張ります。
phpからファイルに追記。メールを送信する方法。
個人的にシフト作成ツールとしてphpを使ったりするので、メモとして
index.phpとsend.phpを作成
ここでやることとしては
- 入力を受け付けるindex.phpを作成
- index.phpに入力フォームを作成
- 入力されたデータをpostする先のsend.phpを作成
- send.phpでファイルに記入する仕組みを作成
- ファイルから読み込んで内容をメールで送信
ちなみに、このメールの宛先を自分にすることで、僕は誰がシフトの申請を出したかが分かるようにしています。
index.php
<?php ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <form action="send.php" method="post"> name:<input type="text" name="name"><br> message:<input type="text" name="message"><br> <button type="submit">submit</button> </form> </body> </html>
とすることで、こんな感じのページを作成できます。
そしてsend.phpを作っていきます
send.php
<?php $dataFile = 'text.txt'; if ($_SERVER['REQUEST_METHOD'] == 'POST') { $name = $_POST['name']; $message = $_POST['message']; $write = $name."さんからメッセージです。\n".$message; $fp = fopen($dataFile,'a'); fwrite($fp, $write); fclose($fp); mb_language("Japanese"); mb_internal_encoding("UTF-8"); $textdata = file_get_contents('text.txt'); $sendmail = mb_send_mail("example@example.jp", "test", $textdata, "From: example.com"); } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>send</title> </head> <body> Sended! </body> </html>
とすれば、送信した際にSended!と書いてあるページに飛びます。
メールの送信のメソッドは返り値がbooleanなので
送信に失敗した場合falseが帰ります。
それを利用して
送信しました!と送信できませんでした。
を条件分岐してあげるといいですね。
実際、自分もそうしています。$sendmailはtrue or falseになっているので。
この先は大体の実行結果です。
index.php
send.php
text.txt
こんな感じです。
メールは試してみる時に自分のアドレスを入れてみてくださいね。