System.out.println("またJavaの季節がやってきた!" + 2);
■ このスレッドは過去ログ倉庫に格納されています
去年の今頃Java学習開始するも挫折
しかし不屈の闘志をめらめらと燃やしながら
そびえ立つ岩壁にいどむため、再びこの地にやってきたのだ!
プログラミング歴は独学Cチョビッツ+独学VBA少々
きょうかしょ
https://www.amazon.co.jp/dp/484433638X
スッキリわかるJava入門 第2版 (スッキリシリーズ) >>444の3通りについてはちゃんとやろうと思う
特に入門本は3つ目の方法でGraphicsを取得しているんだけど
入門本ではImageではなくBitmapを使っている
この辺の違いも明確にしていきたい
ちなみにImageは抽象クラスなのでnewできないが
Bitmapは抽象クラスではないのでnewできる 入門本で玉が跳ね返りながら動くコードを学んだので
高速で跳ね返って動く玉をクリックして捕まえるゲームを作った
クリックのアタリ判定はクリック座標と玉の中心座標の距離を求めてこれが玉の半径以内ならアタリ
イライラするだけのゲームになった JavaでグローバルIPアドレスを毎日記録するアプリを作って
これをタスクスケジューラに登録してあるんだけど、何日か経つと勝手に無効化してしまう
これは一体何が原因なのか
いろいろ調べてみたんだがイマイチわからない
とりあえず正常に動いているタスクの設定を真似して設定を見直してみた
これで動くといいのだが
自分で作ったJavaのプログラムが常時起動しているせいで
タスク実行時にすでに実行中だと判断されてしまっているとか・・・? JavaでグローバルIPアドレスを記録するアプリをつくって
これを毎日起動するようにタスクスケジューラに登録してあるんだけど* 使っているwindowsアプリの入門本は
「作って覚えるVisualC#2017」
なんだけど、VisualStudioの基本操作が紹介されてるという点
どういう流れでアプリをつくっていくのかが分かるという点
この辺がいい
学習の通過点としてこういうテキストは必要だと思う
ただ、このテキスト通りに作っていくと次第に分かっていくんだけど
背後で自動生成されている膨大な量のコードがあるという事
結局これが理解できてないと応用が利かなくなるという点に気づかされる
もちろん俺はまだ一部しか理解できない、というか一部しか見てない
「プログラミング経験ゼロでもしっかりわかる」と銘を打っているんだけど
さすがにこれは言い過ぎ感が否定できない
アマゾンのレビューをみると、誤植を指摘している人がいる
正確にどのページのどの部分かと指摘してるわけではないのだが、
大文字と小文字を間違えてるとかうんぬん
おれはまだ全て読み終えたわけではないが、
ここのことを言っているのではないかと思い当たる部分に出くわした
結論から言うと、誤植ではないと思う
あるフォーム@のボタンを押すことで別のフォームAを一時的に立ち上げるという機能を考える
Aは利用後すぐに閉じられるが、必要な時に何度も立ち上げることになる
このときにAで使うデータを@で作って置いて、
Aを立ち上げるたびに引数を使って渡していきたい
ここで、Aを立ち上げるとは、コード上ではインスタンスを生成することになる
Aクラスのコンストラクタに引数を渡してAインスタンスを生成するのだ
ここで引数がintやstringなら簡単なのだが、
引数自体も自作クラス(CategoryDataSet)のインスタンスなのだ
@の側で引数となるインスタンス内にデータを入れてから、インスタンスごとAに渡す流れなのだ
こうなると
1.@の側で生成する実引数となるインスタンス(categoryDataSet1)
2.Aのコンストラクタでの仮引数(dsCategory)
という2つの変数が登場する
これだけでも初心者は混乱する
さらにだ、Aの側ではdsCategoryとは別に、同じ型の空の変数を用意して、これと
dsCategoryをMergeするという手法を使っている(401ページList2)
この変数が
3.Aの側で用意してある変数(categoryDataSet)
つまりだ、
クラス名CategoryDataSet
@の変数categoryDataSet1
Aの変数categoryDataSet
この3つがごっちゃごちゃになって、別々のものだと理解できず、その結果、
誤植だろこれ!となったのではないかと思う
独習なみにしっかりとした説明があればいいんだけど、背後に生成されるコードについては
ほとんど説明はなく、変数categoryDataSetに至っては、俺の見落としがなければなんだけど、
テキスト内に唐突に出現しているのだ
この変数は、背後で自動生成されているFormItem.Designer.cs内の
InitializeComponentメソッドでnewされているのだが、そんなことに触れようものなら
パンドラの箱をあけるようなもので収拾が付かなくなる
仕方なかったのだろう・・・・・ DataGridViewとDataSet、DataTableの関連についていろいろ調べてた
一体どれがどういう目的で使われているのかとか
なんとなく分かった 引き続き入門本(作って覚えるVisual C#)を読んでるんだけど
DataTableに格納されたデータを取得してこれをcsvファイルに書き込むという場面で
こういうコードがテキスト内に書かれている
foreach (MoneyDataSet.moneyDataTableRow drMoney in moneyDataSet.moneyDataTable)
唐突になにやら面妖なコードが出現
foreachに続く丸括弧内のコードなのだが
普通ここに書くコードの内容を考えると、こう推測できる
@「moneyDataSet.moneyDataTable」 というコレクション(or配列)があって、
A「MoneyDataSet.moneyDataTableRow」 という型の要素が入っている
DataSetはエクセルでいうブック
DataTableはエクセルでいうワークシート
ということらしいので、ワークシートの中の行をコレクションの要素をして扱っているようなイメージか
これぐらいで納得できればいいのだが、じゃ実際にこういう機能、
つまりDataTable内に格納されたデータを取り出す場合に
具体的にどういうコードを書けばいいのかを考えると、この程度の理解では書けないのではないかと思う
そこで、ひとまず@、Aは一体何なのかを実際のコードから読み取ってみよう、と思ったわけだ が、見事に打ち砕かれた
@「moneyDataSet.moneyDataTable」
moneyDataTableがコレクションまたは配列ということであれば、どこかでそういった宣言が
なされているはずだと考えた。もちろん自分でそういったコードを書いた覚えはないので
自動生成されているコードがあるのだろう
そこで、moneyDataTableにカーソルを合わせ右クリ→定義へ移動
するとMoneyDataSetDesigner.cs(これをデザイナと言うそうだ)内に移動する
MoneyDataSetクラスのプロパティとしてmoneyDataTableが定義されているようだ
public moneyDataTableDataTable moneyDataTable {
get {
return this.tablemoneyDataTable;
}
}
これによるとmoneyDataTableを取得すると同じクラス内の変数tablemoneyDataTableが
かえされると・・・もうここでギブアップしたくなるが先に進む
つまり、moneyDataTableはtablemoneyDataTableのゲッターのようなもんで
moneyDataTableの正体はtablemoneyDataTableという認識でいいのか
いや、ゲッターならスペルは同じにして頭文字の大文字小文字変えるだけにしてくれとか
そういうのはなしなんだろうな・・・
取り合えずそういうことみたいなんで、tablemoneyDataTableを同様に右クリ→定義へ移動
すると同じクラス内のここに移動する
private moneyDataTableDataTable tablemoneyDataTable;
「moneyDataTableDataTable」というクラスの変数として宣言されている
この辺のクラス名や変数名をみてると頭が痛くなってくる
moneyDataTableDataTableを右クリ→定義へ移動
public partial class moneyDataTableDataTable : global::System.Data.TypedTableBase<moneyDataTableRow>
ふぅ・・・もうやめたほうがいいのか・・・
これはよくみると同じMoneyDataSetクラスの内部に設けられたインナークラスのようだ
TypedTableBaseクラスを継承している
わからん!
が、このクラスの中をずっと見ていくと、これか・・・と思い当たるメソッドを発見
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
独習を復習し直さないとこれは理解できない
インデクサーを使っているんだよねこれ
独習441ページのコードと類似点が多い
この辺からコレクション的な何かを「感じる」
これぐらいにしておこうか・・・
俺の実力だとこれ以上やっても理解するまでにメリット以上の時間がかかりそうだ
それより独習をちゃんと復習してもう少しコードを読解する能力を身につけた方がよさそう https://ohke.hateblo.jp/entry/2016/12/03/231909
>・DataSet、DataTable、DataColumn、DataRowを継承したクラスを使う
>・プロパティを介してDataTable、DataColumn、DataRowの値へアクセスできる
デザイナを使った、つまり自動生成されたコードの特徴だそうだ
継承とプロパティを介したアクセス
知識ある人には便利なんだろうが、おれにとってはこの2つが理解を拒む壁となってそびえ立つ
DataSet関連のコードはデザイナを使わなくても組めるので
分からなかったら自分で一から書いていった方が良いのかもしれない
そう思って基礎的なコードをいくつか書いてDataGridViewで表示させてみた
この辺はこれぐらいでいいかと思う
続けていけばそのうち分かることもあるだろう >>452の最後のコードはメソッドではなく、まさにインデクサーそのものか
(再掲)
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
今、独習のインデクサーのところを見直しているんだけど、
インデクサーはぶっちゃけて言えばインスタンスの配列化をするための技法
つまり、moneyDataTableDataTableクラスのインスタンスを配列化しているといえる
そして、moneyDataTableDataTableクラスのインスタンスがtablemoneyDataTable
で、こいつをそのまま戻り値として返しているのがmoneyDataTableプロパティ
>>451 @「moneyDataSet.moneyDataTable」は
MoneyDataSetクラスのインスタンスmoneyDataSetのプロパティmoneyDataTableであり
これにより上に書いたような流れで、最終的には
moneyDataTableDataTableクラスの配列化されたインスタンスを意味することになる
この配列の要素となっているのが
((moneyDataTableRow)(this.Rows[index]))
であり
簡単にいえば
Rows[ ] の要素となるのだろう
Rowsにカーソルを合わせると
DataTable.Rows このテーブルに属している行のコレクションを取得します
と出てくる。継承元となっているDataTableがここででてくるわけだ
そしてついに、コレクションという言葉にたどり着いた
道が険しく長すぎる
これでいいだろと言いつつ、調べた結果なんとなく分かった気がしてきた
(配列配列といっているが実際にはインデクサーによる配列的ななにかで実際に配列と行って良いのかは知らない) 独習読んでると、いや、こんなの使わないだろ〜
少なくとも自分では使わないよ、とか思うところが結構あるんだけど
デザイナ使った場合、デザイナで自動生成されたコードから
何かを取得して自分のコードで使いたいと思った時、
つまり上に書いたような場合なんだけど、
こういうときに自動生成されたコードが理解できてないと全くコードを書けない
とするとやはり独習レベルの知識は頭に入れておかないとダメなんだろう
道は長いぞ! テキストボックスをデザイナでForm1上に置くことにより自動生成されるコード
テキストボックスのNameプロパティをmyTextBoxとした
特に大事なのはmyTextBoxがTextBoxクラスのインスタンス変数名として「も」利用されているという点。
private System.Windows.Forms.TextBox myTextBox;
//↑Nameへの代入値がそのままインスタンス変数名としても使われる
//
// myTextBox
//
this.myTextBox.Location = new System.Drawing.Point(13, 13);
this.myTextBox.Name = "myTextBox";
this.myTextBox.Size = new System.Drawing.Size(100, 19);
this.myTextBox.TabIndex = 0;
//
// Form1
//
this.Controls.Add(this.myTextBox); StreamReaderを使う時、一行ずつ読み込むとして
whileの繰り返し条件として使う部分
StreamReader sr = new StreamReader(path);
@while (sr.EndOfStream) { }
Awhile (sr.Peek() >= 0) { }
Bwhile (sr.ReadeLine != null) { }
@、Aは正解
Aは少し古い方法で次に読み込む文字のint型整数値(Char型の中身)を返す
読み込む文字がないと「-1」を返すので、0 以上で有る限り、という条件にする
@のEndOfStreamがプロパティであるのに対してPeekはメソッドなので丸括弧忘れないこと
Bはダメ
読み込む行がないとReadLineがnullを返す事を利用しようとしたものだが、これはダメ。
理由は、ReadLineは単純にチェックのために使いたかったのだが、
実際にここで使ってしまうと、読み込み済として一行進めてしまい、
whileブロックの中で読もうと思っていた行を先取りしてしまう
エラーが出るわけではないが使えない
別途変数を用意して使う方法も考えられるが、そこまでしなくても@、Aがあるので・・・ >>451
@「moneyDataSet.moneyDataTable」関連のコードの位置
【moneyDataSet】はForm1.Designer.csで宣言されるインスタンス
private MoneyDataSet moneyDataSet;
↓
【moneyDataTable】はMoneyDataSet.Designer.cs(以下同じ)、MoneyDataSetクラスのプロパティ
public moneyDataTableDataTable moneyDataTable {
get {
return this.tablemoneyDataTable;
}
}
↓
【tablemoneyDataTable】MoneyDataSetクラスのフィールド
private moneyDataTableDataTable tablemoneyDataTable;
↓
【moneyDataTableDataTable】MoneyDataSetクラスのインナークラス
public partial class moneyDataTableDataTable : global::System.Data.TypedTableBase<moneyDataTableRow> { }
↑のインデクサー↓
public moneyDataTableRow this[int index] {
get {
return ((moneyDataTableRow)(this.Rows[index]));
}
}
A「MoneyDataSet.moneyDataTableRow」関連のコードの位置
【MoneyDataSet】MoneyDataSet.Designer.csの中のクラス
public partial class MoneyDataSet : global::System.Data.DataSet { }
↓
【moneyDataTableRow】↑のインナークラス
public partial class moneyDataTableRow : global::System.Data.DataRow { } 頼まれたんでVBAやってるんだけど
VBAでも普通に正規表現使えたのか
知らなかったわ
IEがらみのライブラリかなんか使うみたいだけど
C#で正規表現結構やったんで役に立った VBAに没頭
自分が作ったものじゃないんだけど、あるwebアプリがある
現在ブラウザに表示してる特定のデータをCSVで吐き出す機能を持っている
このCSVからデータをエクセルに取り込んで加工するということをやってる
ただ、
大したデータ量ではないのに、CSVを作らせるのに1分ぐらいかかったりして結構とろい
ローカルで作成するんじゃなくて、鯖に作らせているようだ
そこで、IEによってローカルに取込み済のHTMLを横取りして加工できないかと。
つまり、HTMLスクレイピングをVBAでできないかと思って
ボトルネックになりそうな部分をちょっと触ってみたんだけど、
意外といけそうなんだよなぁ
とりあえず、CSVを使うバージョンを作ってから
暇な時にHTMLスクレイピングやってみようかな メソッドたくさん作ってからどれ使うかあとから決めると頭が整理できていいな
以前はひとつのメソッドを作り込んでたんっだけど
これをやってしまうと、別のメソッドとして切り出した方が
いい機能まで突っ込んでしまって融通が利かなくなる
ちょっとした機能でもどんどん独立させて作る
同じ機能でも少し違うやつが考えられるなら、全部作ってみる
作ってからどれ使うか選びながら組み立てていく
あと、Functionを作ったら、すぐ下にテストのためのメソッドを作っておくと何かと便利 あと、複雑なロジックは紙にシャーペンで書く
絵や図を書き加えながら、コードを書いていく
消しゴムも必須
やっぱ深く考えるにはアナログが一番いい HTMLスクレイピングというかウェブスクレイピングをVBAでやってるんだけど
Dictionaryないかなと思って調べたら、一応使えるようだ
しかし、使ってみたら、ソートの機能すらない
仕方ないので自分で書いてたんだけど、どうもうまく動かない
この原因探しが大変だった
結論から言えば、forのカウンタの部分で最大値を指定するわけだけど
ここに同じforブロックのなかで変化してしまう変数を使ってしまっていた
繰り返し処理の途中で予期せず最大値が変化してしまい、エラーに繋がっていたのだ
VBAのDictionaryで使うソートの機能をネットで調べると、いろいろと洗練されたコードが出てくる
こぴぺの誘惑にかられたのだが、無骨なコードになってしまうとは言えども
この程度自分で書けないのも悔しくて、、あー疲れた 列挙体初めて実戦で使ってみた
これ便利だな
要はbool系は2つしか選択肢ないけど
これをいくつも増やした感じか
switchというかvbaだとselectなんだけど
これにも列挙体使えるし 正規表現をまともに使えるようになるとグンと幅が広がるわぁ 戻り値のないFunctionはSubとどう違うのだろうか ふぅ大体終わったぜ・・・・
今回のVBAプログラムは処理が重くて表示が固まるのが特徴のひとつだった
これをどうやって軽くしていくかが課題
もっと速くなると思うけど、一応固まらないようにはなった C#に戻るとするか・・・とか言いながらVBAに足引っ張られそうだ 昔書いたコードみると書き直したくなるわ
あまりに酷すぎる プログラミングばかりやってたらアジアカップ見るの忘れてたわ
次の試合から録画する
このタイミングで決勝が日韓戦だと妙な盛り上がりを見せそうだ! 凄くがんばってるなぁ・・・頭の下がる思いでみてる。 独習最初から読み直してる
コードかきかきしながら
おれぐらいすぐ忘れる人間はこうでもしないとな
>>473
ぐへへへへへ これからはクラスを作ったらドキュメンテーションコメントを使っていくことにする
///
これ 時間がなくてちょびっとずつしか独習読めないが
これでいいのだ いままでちゃんと覚えてこなかった基本的な事を読み返しながら覚えるようにしてる
例えば値型のサフィックスとか表になって紹介されてるようなやつ vbaでのIE操作に脱線してた
これ面白そうなの作れそうなんだよなぁ null条件演算子
null許容型
三項演算子
null合体演算子
? を使うこいつら if とか switch とかすごく基本的なもの復習した
基本とかいいつつ独習は細かい論点も触れるので忘れてるところもあった ん〜
いろいろ試しているがvbaからhtmlが取得できない いろんなもの作れるようになってきた
IEコントロールおもろいな
VBAだけど 今日もずっとVBAいじってた
リンククリックしてウィンドウを閉じたり開いたりしてると
いろいろエラーが出てくるんだよね
再現性の高いエラーならいんだけど、ネットと関わるエラーはそうじゃないものが多くてやっかい
とりあえずはエラーがでないようなのを作ってみたんだけど
時間を置いて何度も繰り返さないと確信もてない
なぜか時間を置いてからもう一度やるとエラーがおきてたんでその辺気をつけないといけない 新しいウィンドウをIEで開いた時なんかに
開ききる前にIEを捉えようとするとエラーが出る
見た目開いたように見えても読み込みが不十分だったりすることがあるから
IEを掌握する処理をループで回すのがキモとなるようだ CStr と Str の違い
Str()は、符号の1桁分が必ず確保されていて、
数値が正の時の戻り値の頭にはスペース(空白)が入ります。
Cstr()は、プラスのときにスペースは入りません。
これな・・・・これなんだよ
やっと原因見つけたわ windows10だとIE使えないと思ってたんだけど
機能追加でInternet Explorer11が使えるのか
知らなかったわ
ウェブアプリでIE使ってる場合はそのまま移行できるってことかな
その辺勉強してないからわからんが ふ〜む
EdgeをVBAから操作することもできるようだ
でもWebDriverとやらをダウンロード・インストールしないといけない
これができない環境だとやはり厳しいのかもしれない
https://www.ka-net.org/blog/?p=6018
WebDriverを使わない方法もある
https://www.ka-net.org/blog/?p=6033
しかし公式サポートないそうだ 最近VBAでプログラミングするときは
public宣言をできるだけ避けるようにしてる
Subプロシージャはメインとなるひとつだけにして
あとはFunctionを使う
戻り値が欲しいときFunctionの戻り値を使えば良いんだけど
使い勝手が悪いときは、Subプロシージャ内で変数宣言してから
これを参照渡しすることにしてる
昔は大量のPublic宣言された変数があって見通しが悪かったんだけど
この方法に変えてからマシになった感じがする
こういうやり方が正しいかどうかは知らないんだけど windowsのタイムスケジューラってなにが原因かよくわからんけど
いつのまにか無効になってて一日一回設定してあるプログラム起動が
実行しないようになっちゃうのな
設定変えていろいろやってるんだけど、もういっそのことC#で常時起動の何か作って
そこから実行するようにしようかな
常時起動のJavaプログラムもあるからそこからやってもいいんだけどせっかくだし 忙しくてなかなか再開できないわい
また秋ぐらいから再開しようかなぁ
その頃になれば時間ができるだろうから VBA漬け
エラー処理までちゃんと作らないと気が済まなくて
暇な時間がVBAに吸い取られていくのだ 今期は正規表現が使えるようになったのが大きな収穫だった
C#の独習で覚えたんだけどVBAでも使えるんで大活躍
今日はVBAの入力フォームを作らなくてはならぬ 入力フォームのテキストボックスに特殊なデータを貼り付けたいとおもって
SendKeysってのが使ってみたんだけど、今のところうまくテキストボックスに入れることができない
が、その代りに、VBEのコードのカーソルが当たったところに指定した文字列が入力されてるのに気づいた
コードを操作出来ちゃうことになるんだけどどゆことよw 正規表現を使えるようになったとか書いたけど
よくやってしまううっかりミスに気づいた
しかも自分ではそう簡単に間違いだと気づけないやっかいなやつ
アホみたいなミスなんだけど
"\d"
"\D"
を
"{\d}"
"{\D}"
と書いてしまう
これまでにも何度もやってて、気づけなくて結局他の表現方法使ってたんじゃないかと思う
ほんとにアホみたいなんだけどなぜか自分では気づけなかった
今回相当時間かけて悩んでようやく気づいたw
たぶんだけど、
"\s"
"\S"
とかでも同じような事をやってたと思う
まじで注意 今作ってる入力用フォームでエンターキー押したときにあるテキストボックスから別のコントロールに
フォーカスが移るのを阻止したいと思っていた
別のコントロール全てにTabStop=Falseを設定すれば実現できるんだけど
それだと別の問題が生じるので、できたら他の方法をとりたかった
そこで、
対象となっているテキストボックスに
MulitiLine = True
EnterKeyBehavior = True
を設定することで解決
このテキストボックスは一時的に入力を受け付けるだけの特別なものなので
表示される内容は問題にならないのでこれでOK
ちなみに、EnterKeyBehaviorプロパティはTextBox内でエンターキーを押した時に
改行する機能を持たせるもの。(デフォルトだとTextBox内での改行はctrl+Enter) KeyDownのプロシージャを作って、
If KeyCode = vbKeyReturn Then 〜
を記述することでエンターキーの無効化を試みたんだけどこれは失敗だった
Ifブロック自体は働くんだけど、おそらくそのあとに、フォーカスが移る機能が働いてしまうみたいだ
フォーカスが移ったあとに戻す方法もやってみたけど、これは成功した
しかし、フォーカスが移った先のコントロールに影響が波及するのでこれも避けたかった
よって>>501の方法がベスト 上とは関係ないけど
別のところで使えるかもしれないプロパティを見つけたので書いておく
TakeFocusOnClickプロパティ
コントロールがクリックされたときにフォーカスを取得するかどうかを指定します。
True ボタンはクリックされた場合にフォーカスを取得します (既定)。
False ボタンはクリックされた場合にフォーカスを取得しません。 以前つくったものについて高速化を図ろうと思っている
そのうちだけど。
グローバル変数が多い糞仕様を直したいんだけど
ここをいじるとグローバルが故に影響の大きさが怖い
グローバル変数をさわるとしたら、もう一度全部一から作り直す気持でかからないといけない
今のところは、ネストの深い場所で、ワークシート関数へ置換えができないかを考えている
特に、遅くなりがちなセルの値を取得するようなもの
具体的にはforで回しながらIfで一致を試みるようなコードに
Find関数やCountIf関数を使えないか模索したい 二点
・TextBox1_Changeは、テキストボックスに、他のボタンやプログラムを使って
今表示されているものと同じ内容を表示させた場合には働かない
当たり前といえば当たり前だけど、文字列の再入力全てに反応するのではなく
文字列の内容が変化したかどうか、そこに反応する
・Val は文字列を数値に変換する
Valueの略か? TextBoxとかのKeyDownイベントで
Ctrl + c とかを判別する時、
If Shift = 2 and KeyCode = vbKeyC とするのが正解
If KeyCode = vbKeyC and Shift = 2 とするのは不正解
下のコードだとCtrlを押した時点ではCを押していないため
Cを押す前にifブロックをそのまま抜けてしまう
ちょい時間なくて未確認だけどたぶんこうかなと思っている >>506は間違い
どちらもちゃんと機能する
ただしだ、
明日書こう ただしだ、
上に書いた例だと
Ctrl+c の話なんだけど
c だけを押した時も別の機能を持たせたいとする
このときに
If KeyCode = vbKeyC Then
(処理)
ElseIf Shift = 2 And KeyCode = vbKeyC Then
(処理)
End If
とするとctrl+cが働かない
If Shift = 2 And KeyCode = vbKeyC Then
(処理)
ElseIf KeyCode = vbKeyC Then
(処理)
End If
だとうまくいくようだ あと、今まで知らなかったことを知った
なんでこんなことを知らなかったんだろうと今更ながら衝撃を受けた
VBAで書いたFunctionプロシージャを
ワークシート関数として使う事ができる
これは知らなかった
たぶんVBAやってる人は当たり前に知ってることなんだろうけど
独学でやっていたせいかこんな大事な事を知らなかった
ワークシート関数をVBAのコードで使うと便利だし高速化に繋がることは知っているんだけど
逆があるとは!
ワークシート関数の優れたところは、簡単な記述でリアルタイムにセルに
値を反映させることができる点。
これを使えば、今まで躊躇してきた問題も解決できそうだ VBAのクラスモジュールはほとんど使ったことなかったんだけど
ネットでざっと読んでみるとJavaやC#のクラスと同じような仕組みだとわかる
どちらかというとC#か
以前数回使ったことあるんだけど、あまりよく分からないまま使ってた
オブジェクト指向の言語勉強してからもう一度学び直すと、なるほどなって思える
そこでVBAのもう少し高度な参考書をぽちってみた
入門レベルでは決して足りない実務に必須のスキルとは ExcelVBA 実戦のための技術
単行本 ? 2018/5/24
沢内 晴彦 (著)
今まで作ってきたものを見直すために使えるかもしれない 昔作ったVBAのコードを数時間いじって高速化を試みてみたんだけどことごとく失敗に終わった
高速化とか考えずにとりあえず作ってみたっていうコードが一番速かったという結末
コードの5カ所ぐらいで時間計測してみたら、処理が遅くなっている場所を読み違えていたようだ
ただ、主因となっているところは複雑なコードではなく、改善の余地があまりない
難しいもんだ うぉ・・・高速化成功した・・・
所要時間が1/5に短縮!
5000個ぐらいのセルの値をクリアするコードなんだけど
クリアしちゃだめなセルもある
セルの値が、10パターンぐらいの文字列のどれかに当てはまるなら、そのセルはクリアしちゃダメ
んで、
たぶん一致不一致の判定で時間かかっているんだろうと思って
Likeとアスタリスク使う方法、正規表現使う方法、10パターンの文字列を配列に格納したり
コレクションに格納したり・・・
いろいろやってみたんだけど大差なし
どうやら、実際に消し込む作業に時間がかかっているということが判明
Cells(i, j).Value = "" や Cells(i, j).Clear より
Cells(i, j).ClearContets の方が速いということはわかったんだけど
それ以上の方法が見当たらなかった
で、いろいろググってたんだけど、解決方法は以下の通り
10パターンの文字列は配列だろうがコレクションだろうが大差ないから適当になんかに入れておく
一旦5000個のセル値を配列CellsDataに格納する方向で進むんだけど、
CellsDataの値をひとつずつ10パターンに当てはまるか判定して
当てはまる時だけセル値をCellsDataに入れていく
当てはまらない時は入れないから、そのセルに対応するCellsDataの要素には何も入らないことになる
こうすることで、CellsDataの中身は、必要なセル値を消去した後の表と同じ内容となる
そして、この消去用配列CellsDataを使って、一気に書き込んでいく
Range(Cells(), Cells()) = CellsData
これ↑が突破口だった
よく考えるとこれまで何度か読んだことがある話だったんだけど、思いつかなかった
大量のデータ消去には消去用配列をRangeに一括書き込みすることで高速化が図られるのだ!
これは何も消去だけに限った話ではないのかもしれないんだけど、
単なるデータのセルへの書込みで目立って遅くなったことはない
とするとやはり消去時に特に効果が出る手法なのかもしれない データ書込みも同じようにしたら所要時間がさらに短くなった! 新しく買ってきた本ちょっと読んだけど知らなかったこと多い
Dim i, j as integer
とかいまだにやってる人がいるが・・・・
と書いてあったのだが、はい、わたくしです
知らなかったわぁ
これ i がVariant型になっちゃうそうだ
たぶん勉強始めた頃にこう書いてあったサイトを真似しちゃったんだと思う
こう書いてあるサイトや参考書が結構あるから勘違いしてるひとが多いそうだ
正確には
Dim i As Integer, j As Integer
カウンターぐらいじゃそう問題は起きないかもしれないけど
他の型の変数も同じように定義してきたから
これが原因でわけわかんなくなったエラーもあっただろうな >>515の続きだけど、ワークシートからのデータ取得も
一旦Range型変数に一括取得してから
Rangeから配列に一括代入
そのあと、必要な操作をしたほうがよさそう
今までは必要なデータのみを for や If とかを使って
ワークシートから抽出して配列に代入してた ちょいおかしいか
とにかく不要部分も含めて配列に一括取得してから操作したほうが速いかもって話だ 列挙体便利すぎ
可読性が全然違うわ
セルに書き込んだ設定値を拾って配列に入れて使ってたんだけど
Ary1(1, 1) = Ary2(1, 2) & StrConv(Ary2(1, 1), vbWide)
みたいな書き方してたから、わけわからんコードになってた
今時間見つけては、過去に作ったでかいプログラムを作り直してる
作り直す上での課題はたくさんあって書き切れないんだけど
この前買った本をもう少し読んでから本格的に取りかかった方がよさそうなんだよな
とか言いながらコードどんどん書いちゃってるけど
列挙体はネストができるともっとよかった vbaでクラスモジュールを使う必要性はない、あっても限定的だ
とも言われている
でも、ざっと勉強した感じでは、コードの可読性やメンテナンスのしやすさを考えるとそうとも言えないという印象を持った
一度しっかり使えるようにしておきたいので
実用的なお手本コードを何度か書いてものにしようと思う
参考書にはColectionやDictionaryと組み合わせた処理が書いてあるので
これをちゃんと理解して使えるようにしたい https://qiita.com/pregum/items/071f72969d72d90cf826
ここにもCollectionとDictionaryを組み合わせるコードが載っている
使い方は参考書に載っているものとは違うんだけど、
基本的に大事な事は
DictionaryはExistsメソッドによる検索機能が優れているので
検索機能を強化するために使っているという点
CollectionとDictionaryは似ているので
何のために使い分けているのか把握しておかないといけない
じゃCollectionの利点はというと
Dictionaryと違ってItemのみの登録ができるという点なのか
なので、一次元配列を使おうかという場面でCollectionはいい対抗馬になる
ここに検索機能をつけたい場合は
何かを媒介としてDictionaryとつなげる
ここも参考にした
http://blog.livedoor.jp/minus_alpha/archives/4233055.html ええっと、>>525の何かっていうのは、Collectionのインデックス番号だな
Dictionaryにはこのインデックス番号をItemとし、Keyを検索ワードとして登録していくわけだ
IndexNum = myDic.Exists(検索ワード)
とすると検索ワードに対応するインデックス番号を取得できるので、
こいつを使って、Collectionの要素を参照していく
myCol.Item(IndexNum)
とかいう感じで プログラムの組み直し終わったわ
以前の1/4ぐらいの時間で終了
まぁ以前のコードも参考にしてるから当然なんだけど
改変部分も結構ある
以前より使い勝手がよくなったと思うし処理速度は1/10ぐらいになっている
Dictionaryを組み込んでないのが心残りだわ
やっちゃおうかな・・・メインの部品に組み込んでいくから影響範囲が大きいんだよな んー
VBAでも構造体が使えたのか
これってクラスモジュール使うのと同じような場面で使えるなぁ
https://www.sejuku.net/blog/39307 構造体がデータを格納する機能だけであるのに対して
クラスモジュールはメソッドがついてくるから、その辺まで拡充した役割が必要な時は
クラスモジュールに軍配があがるのかなぁ
あと、セッターで適正値に直したり排除したりできるし
やっぱ複雑なものはクラスモジュールに任せると可読性あがりそう
今回のプログラムも結局クラスモジュールは中心的な処理の中には入れなかったし
これも心残りだわ Dictionary は Exists を目当てに使うのが正解なのもしれない
これ便利
だけど、Key が対象となるわけなので、同じものが重複するようなデータには使えないな
それがネックか ふぅぅぅぅぅ
やっとわかったぜ・・・
ユーザーフォーム上に動的配置したコントロール間で相互にアクセスする方法
もし静的配置であれば簡単で
例えば
TextBox2のクリックイベントプロシージャ内で
MsgBox UserForm1.TextBox1.Value
と書けばいいだけ
動的配置した場合はこういう風にはアクセスできない
今までも動的配置によるコントロール配置はやってきてるんだけど
相互アクセスはやったことがなかった
クラスモジュールにイベントプロシージャを置く事になるんだけど
この中で
動的配置されたテキストボックスのコントロール名を使ってアクセスするというのが解答のようだ
つまり、ユーザーフォームで動的配置したときに、アクセスしやすいように
Nameプロパティで名前をつけておく。
例えばTargetTextとしよう
その上で、クラスモジュールで
Dim tempTextBox as Control
Set tempTextBox = UserForm1.Controls("TargetText")
とすれば
MsgBox tempTextBox.Value
でアクセス可能
疲れたああああああああああああああああああああああああああああああああああああああ ユーザーフォーム上のコントロール動的配置についてもう少し理解を深めるために
単純なプログラムを作ってテストを重ねてみた
ぐぐっても出てこない部分は想像に頼ってるんだけど、大体理解出来たと思う
たまにこういう事をやらないと無駄なコードを書くことになる
今回は今まで書いてたコードの間違いというか、無駄な部分をいくつか見つけたのが収穫だった よし、機能的には大体やりたいこと全部できた
あとはエラーが出ないか現場でチェックだな
一仕事終わった クリップボードを経由しないコピーを勧める理由
http://blog.sbe.tokyo/20150909/470/
なるほどなぁ
こういう考えもあるんだな
確かにいろいろと問題あってめんどくさいとは思っていた
これに関連して
罫線のコピー
http://blog.sbe.tokyo/20150115/203/ VBAでエラー処理をSubプロシージャごとに書いていく作業が刺身にタンポポ乗っける作業と同じぐらい苦痛
これC#で自動化するプログラム書いちゃおうかな
単なる文字列操作だからできるよな
ここ数ヶ月やってなかったんで忘れてしまったが、C#の課題としておくか >>537を参考に罫線をコピーするコードを書いてみたんだけど死ぬほど遅い
やっぱりCopyメソッド使った方がよさそうだ C#の参考書少しずつ読んでるんだけどVBAとダブる部分は
VBAだとどうなのかをメモしてる
この辺ちゃんとやっておかないと記憶があやふやになる VBAとしっかり比較しながらやると勉強になる
C#の知識が増えるころにはVBA忘れる現象に少しは歯止めがかかりそう
というか比較しながらやると知識の固定にも役に立ちそうだわ
除算系の算術演算子とか基本的なのも忘れるからなぁ
独習読み込むのと同時に
C#でちょっとしたウィンドウズアプリ作ってる
URLをテキストボックスに入れてボタン押すと
サーバーにアップロードしてあるZipをダウンロードして解凍して
日付で名前をつけたフォルダに入れるってやつ
こういうのってエラー処理やら利便性無視すれば簡単にできるんだけど
いろいろ考えちゃうと難しくなる
適当なところで見切りつけて終わる予定だけど。
ググって出てくるコードみると、イベントにマルチキャストデリゲートだったか
そんなの使ってたりするんで理解しようとすると大変だ
GUI関連をきちんと理解するのに役に立つ本があるといいな ■ このスレッドは過去ログ倉庫に格納されています