Excel VBA 質問スレ Part57
■ このスレッドは過去ログ倉庫に格納されています
ExcelのVBAに関する質問スレです コード書き込みや作成依頼もOK ※前スレ Excel VBA 質問スレ Part56 http://mevius.5ch.net/test/read.cgi/tech/1534976724/ >>520 3回以上セルにアクセスするなら確実に配列に取り込んだほうが早い。 体感出来ないのはコードが完全に最適化出来てないだけ。 あと数式の埋め込まれたセルがあったりするとあり得ないくらい遅くなる。 (ある程度はスイッチで解消できるけど) あとInputはめちゃくちゃ遅いよ。 バイナリモードで開いて一括読み込みがオススメ。 http://tetsucom.blogspot.com/2011/03/vba_9799.html このサイトでは数倍しか差がついてないけど、元データの行数が増えるほどInputと差が開く >>522 アップロードしたファイルに店名が含まれているんだが大丈夫か・・・ 皆さん助言ありがとう。 処理のイメージとしては、1行ずつ読み込んで色々判定した後、1行ずつ出力していく感じです。 頂いた助言を試してみて、 事前にeofまでのループ処理で変数をカウントアップさせて、必要な行数を配列に格納させることはできました。 バイナリモードの件と合わせて、パフォーマンスの向上を目指しますm(_ _)m >>526 Rangeオブジェクトへのアクセス回数を減らすよう意識すると、案外パフォーマンスが上がったりする。 あとオブジェクトの特定のプロパティ・メソッドがやたら遅かったりすることもあるから注意。 >>525 気がつきませんでしたが、ダミーデータなので大丈夫です >>526 1行ずつ出力じゃあまり恩恵無いかもしれないけどまとまって出力すれば劇的な変化がある。 Dim i As Long Dim j As Long Dim varRng() As Variant Dim t As Single t = Timer For i = 1 To 50000 For j = 1 To 50 Cells( i, j ).Value = i + j Next j Next i Debug.Print Timer - t t = Timer Redim varRng( 1 To 50000, 1 To 50 ) As Variant For i = 1 To 50000 For j = 1 To 50 varRng( i, j )= i + j Next j Next i Range(A1:AX50000).Value = varRng Debug.Print Timer - t 実践的に練習用の課題を解いていけて、段階的にスキルアップできるサイトないですか? Range(1,1).Value = 1-1 これをやると、1月1日にExcelが日付と解釈して変換する。 これを防ぐにはどうしたらいいですか。 文字列として格納するために""で囲むという手があるがそれをやりたくない。 理由は値(1-1)に加工していじってるから。 ちなみに、1-1は番地のつもりです。 >>531 書式を明示的に文字列にしてからやってみたら? .NumberFormatLocal = "@" >>531 その式だと1-1で0が格納される訳だが? セルに文字列として格納させるなら532の方法か、先頭にシングルクォーテーションを付与 1件だけなら 「Range(1, 1) = "'1-1"」でもいいかもしれんが、沢山あるようなら配列を使って一発代入するかな。 >>459 です。 >>521 さんありがとうございます。 文字化けしない環境で試してみたら、画面は見えました。 ですが、肝心のコードが見当たらない・・・orz シートに記載されてる情報を見る限り、恐らく>>521 さんのが一番私が求めているものに近いかな、と思いました。 >>521 さん、ダウンロードしてもコードが見えないので、 このスレにコードをコピーしてもらえないでしょうか? Cells(Rows.Count, 1).End(xlUp).Row これだとhiddenで隠れている行は無視されてしまいます あくまでも最後に入力されている行を取得したい場合はどうすればいい? もちろんhiddenを一時的に表示にする以外方法で 隠れていてもデータ行として扱う方法 ↓ココに操作手順がおいた http://fast-uploader.com/file/7094133678468/ [SQLの編集]タブに編集の仕方が載ってる(denpyouを例にしてるが、編集の仕方は他も同じ) ※ vbaじゃないからな、コードはない ※ ちなみにデータとデータの抽出結果を出力するブックは別でも問題ない 新規に自分で作成したい場合は >>437 ← コレ を参考にしなさい VBAの実行環境をDockerizeする方法を教えてください >>536 used range使えば?最終行取得でググれ UsedRangeはプロパティに変更が加えられたセルを全てカウントアップするから物凄く癖がある うっかり列範囲全体に書式設定なんかしてると最終行は1,048,576行目なんてことになるので注意 >>541 列に対しての書式設定ならそんな風にはならない。 貼り付けするとそうなる危険性はあるけど、今のエクセルは警告出るし、実行に時間かかるし、めちゃくちゃ重たくなるから、マクロ以前にブック修復すべき案件 Do loop関数でウェブ上の変数を取り込んでセルに表示したいんですが、セルA1に最新の変数を表示し、一つ過去のは真下セルに移動する これを繰り返して変数をA列に積み上げいくようにしたいんですが、どうすればよいでしょうか Selenium Webdriverについて質問です。 @chromeを起動 Aあるwebサイトのユーザーページにログイン Bユーザーページ上で作業 という操作を自動化しようとしています。 @、Aは良いのですがBが複雑なため、その部分のコードで試行錯誤しております。 しかしコードを修正するたびに@から行っているため時間がかかっております。 @Aで起動したブラウザを利用して、Bから別のsubプロシージャにして、Bだけ実行して検証したいのですがどのようにすればよいのでしょうか。 下が@Aのコードです。 sub 1() Dim driver As New SeleniumWrapper.WebDriver driver.Start "chrome", "https://aaa.com/login?" ; driver.get ("/") driver.findElementByName("UserID").SendKeys ("yamada") driver.findElementByName("pass_word").SendKeys ("1234") Private driver As SeleniumWrapper.WebDriver Sub Init() @ A End Sub Sub Work() driver.get(ユーザーページ) B End Sub 他のスクリプト言語に変えたほうが楽ですよ >>546 ありがとうございます。 やってみたのですが、getメソッドでSystem.NullReferenceExceptionというエラーが出ます..... 他のスクリプト言語というとRubyということになるのでしょうか? >>547 driverを初期化してないからだと思うぞ。 >>548 大変申し訳ないのですが詳しく説明して頂けないでしょうか.... 勉強不足ですみません >>549 Private driver As SeleniumWrapper.WebDriver ←モジュール領域(各プロシージャの更に上位)でdriverを定義。ただし初期化していない。 Sub Init() ←Initプロシージャを実行する時にdriverを初期化し@・Aを実行する必要がある Set driver = New SeleniumWrapper.WebDriver ←ココ @ A End Sub Sub Work() ←Initプロシージャを実行してからWorkプロシージャを実行すると、色々(B)を実行してくれる driver.get(ユーザーページ) B End Sub 念のため言っとくと俺は>>546 じゃないがついでに解説しただけで、 >>545 が求めているものがこれで満たせるのかまでは関知しない。 質問いいですか? VBAでコールバックを行うとき クラスが対象の場合はCallByNameで行う事が出来ますが 標準モジュールの場合、どうするんでしたっけ? 確かAPIを使った様な気がしたんですが どのAPIを使ってどうするのか 忘れてしまいました。 >>551 忘れたけど ariawase を見れば出てくるんじゃね >>550 とても丁寧にありがとうございます。追加質問させてほしいです。 A: 今回「driver」はオブジェクト変数となるため、定義の際はnew演算子を使用する。またはsetで格納する必要がある。ということで良いのでしょうか? B: >>550 で「ただし初期化していない」とありますが、あるサイトで「vbaでは変数宣言したときに初期化が行われる」という記述を見ました。 これは、setで格納されてないから初期化すらされてない という意味でしょうか。 C: プロシージャが実行されるごとに初期化されればよいならば、private変数の定義をやめて、@〜A、BそれぞれでDim driver As New SeleniumWrapper.WebDriver と定義すればエラーは出ないと思ったのですが、 やはりBのgetメソッドのところで「System.NullReferenceException」エラーが出てしまいました。何故なのでしょうか・・・ 長文ですみません どうか宜しくお願いいたします。 >>553 A: あってる B: だいたいあってる C: まずコードが動くことを確認してから弄れ。>>546 の意図が汲めないならすっぱり諦めて別の方法を考えろ。 流石にこれ以上は自分で調べろ。 追伸 B: とりあえず「値型は宣言と同時に初期化される、オブジェクト型はNewやSetをしてからでないと使えない」と思っとけ C: 要はWebDriverの「使い回し」がしたいという質問に答えたのが>>546 ・モジュールレベルで宣言すれば、各プロシージャ内から変数「driver」を通じて同じ実体(インスタンスという)にアクセスできる ・Initでモジュールレベル変数「driver」を初期化したりStartなどのメソッドを実行すれば、Workでdriverにアクセスした時にその続きのアレコレができる ・逆にInitで初期化やStartその他を実行したにもかかわらずWorkで新たな変数「driver」を宣言したらInitで行った処理が水泡に帰する ・またInit内で新たな変数「driver」を宣言し初期化等をした場合も、Init終了と同時に実体が消えて無くなる 仕事中なんであれこれ端折って書いたので間違ってる部分もあるかもしれんが、「インスタンス」とか「スコープ」とかでググって調べてみてくれ。 >>554 本当に丁寧にありがとうございます。 伝えるのを忘れていましたが、言われた通りにコードを記述しうまくいきました。それを踏まえてのCでした。 インスタンス、スコープで調べてみます。ありがとうございました。 「選択したセルの値を-1する」のに下記のようなプログラムを書いた。 Dim cell As Range For Each cell In Selection cell.Value = cell - 1 Next これはOK。 「セルの値がブランクまたは0のとき、ブランクにする」を追加して、 Dim cell As Range For Each cell In Selection If cell.Value <> 0 Then cell.Value = cell - 1 Else Next としたら「Nextに対応するForがありません」と怒られてしまいました。 どこがいけないのでしょうか? >>556 インデントが適当だからそういうミスに気がつかない else nextとか書く馬鹿にインデントもなにもねーよ Ifは基本一行で済ませるか、If...Then句を書いた後にすぐ改行して同じインデントレベルでEnd If 句を入れる癖をつけろ >>448 レベルアップするたびにポイントをVBAにばかり振り分けてきたんだよきっとw >>556 根本はエクセルのエラーメッセージが明らかに間違っているから混乱する けどプログラムの世界って大体そんなもんと諦める必要がある で、対処法としては >>559 が正解 インデントが適切なら楽勝で気づける問題 >>562 は最悪。開発が超遅くなる 質問です。 テキストファイルの中身をセルに出力する処理をやっているのですが、一部のテキストファイルの文字が正常に出力されません。(縦線 " | "のみが出力される) ただし、判定によってセルの色を変えているのですが、その機能は生きているので、読み込み自体はできているみたいです。 また、全部のファイルで不具合があるわけではなく、特定のファイルの特定のレコードにのみ起こるっぽいです… 補足すると、テキストファイル自体はメインフレームの伝送機能で送ってます。これが原因に関係あるのかはわかりませんが… 詳細聞かれたらお答えしますので、解決にご協力頂ければと思います。 565です。 本題を載せ忘れていました。 原因、改善方法がわかる方いましたら、ご返答願います。 俺はインデントもしっかりでEnd Ifも先に書く派だな、他の言語での閉じ括弧みたいなもんだし >>564 俺はブロックを先に区切らずにダラダラ書いていく方が効率悪いように見えるんだけど、End Ifを先に書かない方が速度上がるの? 本当だったらそうしてみようかな >>565 コンピュータのベンダーや年式が違えば文字コード字形の割り当てが違うことも多い 手順 ・テキストファイルの文字エンコード、記述形式を正確に把握する ・化けた部分前後数行のみのテストデータを作る ・ウォッチウィンドウを活用して原因を探る >>568 INPUTはJCL(COBOLアプリを動かすためのスクリプト言語)をテキストファイルに落としたものです。 特定のレコードなのですが、テキストファイルを確認しても、他の出力されているレコードと見た目は全く変わりません。(スペース、データの末尾にも問題なし) にも関わらず決まったレコードのみに不具合が発生します。 マクロが手元にないため画像は載せられませんが、 JCLについては、画像検索して出てきたものとほぼ同じですので参照頂ければと思います。 >>570 やはり文字コードがきな臭いですかね shift-jis になる仕様のはずなのと、他レコードは大丈夫なため問題ないと判断していたのですが、 vba上でも文字コードを明示してあげる必要がありそうですね メインフレームなぁ・・・最後に触ったの20年近く前で、びっくりするほど覚えてねぇ。 ちょっと気になるんだが、正常に出力されない時に表示される縦線は、 元のテキストファイルにデータとかデリミタとして含まれている文字なのか? それとも変換できなかった文字が縦線に置き換わっているのか? >>556 なんかコピペしたときにend ifが抜けてた >>573 縦線はデリミタではなく、元のレコードにも存在しない文字です。 処理としては、テキストファイルのレコードをそのままセルに出力するだけなのですが… 読み込んだ時点では問題なく、出力したときに縦線に置き換わってる感じですねー >>575 ファイルからレコードを読み込んだら、イミディエイトウィンドウにも出力しておく データをセルに書き込んだあと、もう一度セルから読み出して縦線になってたら中断するようなコードを書く 中断したらイミディエイトウィンドウの内容を確認 どこで化けたか、1つずつ追跡するしかないです 意外なところでミスをしていたり、仕様だったり、落とし穴があるもんです >>575 1.入力するテキストファイルに「ろくでもない見えない文字」が含まれている(たとえば制御文字) →普通のテキストエディタでは見えないことが多いのでバイナリエディタで確認する 2.テキストファイルのレコードを読み取りセルに出力する処理のどこかに問題がある →特定のレコードで発生するということは、特定の文字列のパターンか、特定のレコード数でのみ発生している可能性もある こんな月並みなことしか考えつかないな。 個人的には、文字化けだったとしたら全部縦線に置き換わるのはおかしいと思うが(化けた文字が一切見受けられず縦線だけってのが妙に気になる) とりあえず、どんなコードで読み取って表示してるか出さんと話にならんわ 実はテキストファイルのエンコードがutf8とかだったりして メインフレームだからEBCDICだろ変換前はEBCDICの変換は面倒い >>561 SHIFT-JISのはずって言ってるし、ホスト側に大抵変換ツールあるだろ 文字コードや制御文字の可能性よりプログラムのバグの方が確率高い気がするなぁ まあコード出せばどっちの問題かはだいたい判別できるはず 化けるデータのダンプでもいいけどな 色々と意見ありがとうございます。 コードが掲示できなくて申し訳ないですが、 文字コードについてはホストの変換機能があるはずなので、プログラム上のバグとみてデバックしてみます。 >>567 >>569 正解。 でも、頭の使い方を知らない人にとっては理解し難いんだろう。 頭を使う作業と単純作業を分けるのが自然になってる人はEndIfを先に書く。 他にもEndWithやNextも先に書くな。 Ifまで書いて条件をどこからかコピペするのに気付いた時はIf a Then...EndIfまで書いてからaと差し替えるとか。 あるいはaの差し替えは中身書いた後の時もあるな。 >>577 文字化けはイミディエイトでは分からない場合も多い。 こういう時はデバック用にバイナリで出力するものを作っとくべきだね。 VBA「済まんのう、ワシのインテリセンスが貧弱なばっかりに・・・」 >>585 閉じタグみたいな単純作業を人間がやるのは馬鹿らしいと気付いて別の言語に移行するのが大正解 で、pythonみたいな欠陥言語では空文という概念すらない インチキな制御文で空文を回避する必要がある つまり、cが言語として一番単純で簡単 しかし少し待って欲しい C言語が扱うのはDelegateじゃなくて ポインタだから不慣れな人が使うのは結構危険 コードの作成ができる方がいらっしゃいましたら、助けていただきたいです。 https:〜〜/〜〜〜/〜〜.pdf で終わるURLが1000件以上あり、業務でそのすべてを印刷しなければならないのですが、 1つ1つIEで印刷していくのが大変面倒で、VBAで一気に印刷することができないか 調べたのですが、.pdfで終わるファイルをwebから自動で印刷するのは不可能なようでした。 そこで、その1000件以上あるpdfファイルを一気にローカルに保存できないかと考えております。 具体的には、 A列にひたすらURLを貼り、マクロを起動するとローカルの任意のファイルにPDFが保存されていくようなVBAが組めないかと考えております。 (一気に印刷することができれば、尚よいのですが) どなたかコードを組んでいただけないでしょうか。 お手数ですが、よろしくお願い致します。 curl, wget で、ファイルをダウンロードできる ダウンロードやら印刷やらはPowershellならそれぞれ1コマンドで出来るんだけどね VBAだとそこそこ面倒な気がする 両面2upで印刷とかだとpowershellでも大変じゃないの >>593 難しいだのなんだの言われてたけど、テキトーにやってたら簡単にできて拍子抜け http://fast-uploader.com/start/7094526398997/ Book1.zip を Book1.xlsm にリネームしてくれ A列はファイル名 B列はURL C列はokかNGか。アテになるかどうかはシランので、落とした後のファイル数はなどは確認したほうが良い コードの編集は適当にやってくれ 今はテスト用に3つだけにしている あと保存するファイル名は被らないようにかなり適当に作っている。適当に変えてくれ で、pdf印刷はこの辺に任せるといいと思う https://dekiru.net/article/1745/ あと、参考にしたサイト https://tonari-it.com/excel-vba-windowsapi-urldownloadtofile/ 特に何の関係もない、無害なサンプルpdfが置いてあったサイト http://www.shikisensha.com/pdfs.html >>593 powershellスレで聞いた方がいいよ 一括ダウンロードも印刷もけっこう簡単にできる VBAでもできるけどちょっと面倒だから そこまで簡単にできるならもうここで書いてしまって良いんじゃない? >>593 そんなのjdownloader2とか webブラウザのアドオン使えよw >>600 あれ、そうか PowerShellあんまり知らないから見てみたかった >>601 拡張機能探すのあんまり得意じゃないわ 結局作ったほうが早い >>603 ざっこw >>597 URLDownloadToFile というAPIがあることをいま知った。 これまで都度 MSXML2.XMLHTTP を作って .Open "GET" していた。 API一発ならその方がスマートだしプログラムをそれベースに書き換えようかと思ったけど、 IDとパスワードを渡さなきゃならない場合は使えないのかな? N列に時刻データが入っている 但し一部の行はブランク 時刻データは"00:10:00"のように時・分・秒が指定されている 表上は"00:10"つまり「時・分」のみを表示 この時刻データの分の1桁目が9の時のみ1分繰り上げて0にしたい つまり "00:19:00"→"00:20:00" "00:59:00"→"01:00:00" になるようにしたい セルは複数セルを不連続で選択し、ブランクはパスして 分の1桁が「9」の場合のみ1分繰り上げするにはどうすれば良いでしょうか? >>606 秒はどうするの?19分30秒だったら20分00秒にするってこと? とりま、基本的な処理は分を10で割った余りを求めて、9だったら1を足す それを選択された全セルに対して繰り返す >>606 O1=N1+IF(MOD(MINUTE(N1),10)=9,TIME(0,1,0),0) >>565-586 Ruby で、そのテキストの該当部分を表示して、確かめる。 他の言語でもよい >>606 いったん時刻に変換して、1分足してから、また元の形式へ戻す。 つまり、表示形式 → 時刻 → 表示形式 >>565-586 制御文字の可能性があるから、文字列をバイナリで見る 文字コードや、UTF-8 ならBOM の有無 セルに入力した時に、特別な意味を持つ文字が入っているとか? シングル・ダブルクォーテーションなど? 会社で社内Webのform類のsubmitボタンを押して出てくるデータベースのデータが抽出されるシステムがあります。 (まあ、このようなシステムはどこにもあると思いますが。) これ、どうにかして大元のデータベースのデータを丸ごとExcelにインポートする方法ってないですか? Webのソースを見れば、データベースのサーバのアドレスが書いてあって、それをVBAで取り込む、みたいなのをイメージしているのですが 技術的には可能ですよね? 技術的には可能だがお前には不可能 イメージが見当違いだ WEBサーバ自体をハックできるなら。 大抵PHPか.Net実装でソースからは見えない あまりわたしを怒らせないほうがいいぞ わたしは怒ったら怖いんだぞ コンプライアンス違反で懲戒解雇&賠償請求訴訟起こされたいのなら、止める義理はない >>611 会社のシステムなら上司に相談しろよ 社内規定に違反すると最悪解雇もあるからな >>611 怒らせたくはないけどまともなシステムならクライアントから見えるところにデービーのアドレスは書かれてないよ クライアント↔Webサーバ↔DBサーバ ブラウザがやり取りするのはWebサーバ その先にはアクセス出来ないのが普通 普通に上司経由でシステムの所管部署に相談してAPIを共有してもらった方が安全だろ 自作コードでサーバーを直接叩くのはいろんな意味で危険 焦っとるなプロさんwおまえらプロさんのコードも十分すぎる程危険なんやがw >>611 出発点から「自分で勝手に何かする」というのが間違い。 他の人も言うとおり、まずは自社で管理してるDBなら管理部署に、ベンダのシステムであればそのベンダに、やりたいことを伝えて対応してもらう。 対応してもらうのが無理なら、管理部署やベンダにAPI等を利用してツールを作成して良いか確認を取る。 もしOKなら、API等を利用してツールを自作する。完成したら必ず管理部署やベンタにツールを見てもらう。 勝手にベンダのAPIを利用してSQL発行ツール自作してクビ寸前まで行ったことがある人を知ってる。 大幅減俸で落ち着いたらしいけど今はもういないから実際のところどうだったのかは知らんが。 >>607-609 ども! ワークシート上なら"00:59:00"+"00:01:00"→"01:00:00"みたいに単純に繰り上げが出来るので マクロで同じような計算が出来ないかと考えたんだけど(>>609 さんのコメがそうかな?) 具体的な手順が思い当たらなかったので、原始的なやり方で作ってみました strTime = Format(cell.Value, "hh:nn:ss")でセルの時刻を文字列に読み込み 時(strH)・分(strM)・秒(strS)を切り分け、分の1桁目が9の時だけ intH = val(strH)、intM=val(strM)で数値化した値から sumM = ntH*60 + intM + 1 intH = int(sumM/60)、intM = sumM - intH *60 を計算し これを時刻に直してセルに戻す、という手順で出来ました 先週文字化けの件で質問をした者です。 あれから例のマクロをデバッグし、無事原因がわかりました。 文字コード云々ではなく、単純なロジックミスという落ちでした…。 お騒がせをしましたが、ご助言くださった方々ありがとうございました。 オートフィルターをかけた状態の表を配列に取り込むには、Copy Pasteで一旦どこかに貼るしかないのかな? ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.4 2024/05/19 Walang Kapalit ★ | Donguri System Team 5ちゃんねる