[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『プログラム全体で実行するとうまくいかない』(こっくさん)
はじめまして!
当方理系の学生です。
最近になってVBAを知り勉強を始めました。
マクロを組んで実験データを一気に処理させようと思いちょっと長めなマクロを組んで実行してみました。
ところが、実行結果はうまくいっていませんでした。
指定した計算を全てこなしているブックもあれば、一部の計算が抜け落ちているブックもある。といった具合です。
こちらで思い付く計算間違いなどはネットや専門書(VBAの入門書ですが)等を見て全て直しました。
そして1行ずつ実行してみるとちゃんと指定した計算をしてくれていました。
しかし全体を実行するとやはり最初のようにうまく計算をしてくれないブックが出てきます。
これはpcのスペックが足りないからなのか、
エクセルではなく解析用のソフトを使うべきなのか、
あるいは入門書には載っていないようなプログラム内のギミックがあるのか
VBAのまだ勉強を始めたばかりなのでよくわからないのですが、
なにが原因となっているのか詳しい方がいらっしゃったらご教授頂きたいです
プログラムを組むのに苦労した分原因がわからないのがとても悔しいです。
なにとぞよろしくお願いします。
< 使用 Excel:Excel2010、使用 OS:Windows7 >
物を見ないとなんとも言えないですけど、一部の計算が抜け落ちているブックの
計算が実行されるタイミングの前の処置辺りに、DoEvents を入れてみるとか、
計算はシート上の数式は使わずにVBA内でセットしていくようにするとか、
やっぱり、物を見ないと・・・
(ウッシ) 2015/09/03(木) 15:18
コード、VBAの中身、プログラミング
書いてないとわかりましぇ〜〜〜〜〜〜〜〜〜〜〜〜〜〜ん。
大学生なんですから
きちんと考えてから書き込みましょうね☆
(02) 2015/09/03(木) 15:19
皆さんのコメント通り、コードを見ないと何とも言えませんね。 内容は、難しい数理計算なんだと思いますので、算数音痴のβがコードを見ても理解はできないと思いますが 少なくとも再現テストはできますので。
1行ずつ実行というのはステップ実行をしたということでしょうか? 計算ではありませんが、ステップ実行をすると問題なく処理される。でも普通に実行するとエラーになるというのは 実はVBAの世界ではめずらしいことではありません。
VBAはインタープリータで、かつ、1行ごとに確実に処理しているのではなく、1行を、その処理をつかさどる機能に丸投げ。 で、その行の実行が終わったかどうかはおかまいなしに、次の行の実行にすすむ。 多くの場合は、ここで、エラー(オートメーションエラー等々)になりますが、コードの先頭あたりに On Error Resume Next なんて記述をする人が(特に、古参の、そこそこの権威の方々)おられます。 そういう先生の指導を受けた人は、何の疑問も持たずに、やはり記述してしまう。 実際に、βが現役時代に入社してきた若手が、そういった記述をしていました。
まぁ、エラートラップに限らず、実際には、処理が間に合っていないのに実行されるというのは、ありうることかと。 ウッシさんが指摘されるように、困った時の DoEvents。適切な場所に、それをいれこめばOKになるケースもあります。
いずれにしても、コードを拝見したいですね。
(β) 2015/09/03(木) 15:39
(こっくさん) 2015/09/03(木) 16:37
とくに難しい計算等はないです。
どの部分が悪いのかがわからないので、使ったプログラムをまるまるのせます。
プログラミングに慣れていないので見にくいかも知れませんが、ご容赦願います。
Sub 一括解析()
Dim Pro As Integer Pro = Application.SheetsInNewWorkbook Application.SheetsInNewWorkbook = 1 Dim BlockLineNumber As Integer Dim BlockColumnNumber As Integer Dim CellNumber As Integer Dim count As Integer count = 0 For BlockLineNumber = 1 To 8 For BlockColumnNumber = 2 To 9 CellNumber = 1 On Error Resume Next Workbooks.OpenText "D:\Desktop\実験データ\sample1-" & BlockLineNumber & BlockColumnNumber & "-" & CellNumber & ".txt", DataType:=xlDelimited, Space:=True If Err.Number <> 0 Then Workbooks.Add.Sheets(1).name = "No Data" & CellNumber Else End If On Error GoTo 0 For CellNumber = 2 To 4 count = count + 1 On Error Resume Next Workbooks.OpenText "D:\Desktop\実験データ\sample1-" & BlockLineNumber & BlockColumnNumber & "-" & CellNumber & ".txt", DataType:=xlDelimited, Space:=True Sheets(1).Move After:=Workbooks(2).Sheets(CellNumber - 1) If Err.Number <> 0 Then If (CellNumber > 4) Then GoTo 30 Else Worksheets.Add After:=Workbooks(2).Sheets(CellNumber - 1) Workbooks(2).Sheets(CellNumber).name = "No Data" & CellNumber GoTo 20 End If Else End If On Error GoTo 0 20 Next 30 For CellNumber = 1 To 4 Dim SheetsName As String Dim NoDataName As String SheetsName = Sheets(CellNumber).name NoDataName = "No Data" & CellNumber If SheetsName = NoDataName Then Columns("A:A").ColumnWidth = 30 Rows("1:1").RowHeight = 120.75 With Sheets(CellNumber).Range("A1") .Value = "×" .Font.Color = -16776961 .Font.Size = 50 End With Else With Sheets(CellNumber).ChartObjects.Add(230, 50, 300, 200).Chart .ChartType = xlXYScatterSmoothNoMarkers .SetSourceData Source:=Sheets(CellNumber).Range("B5:C165") End With With Sheets(CellNumber).ChartObjects(1).Chart .HasTitle = True .ChartTitle.Characters.Text = BlockLineNumber & BlockColumnNumber & "-" & CellNumber & "の Vbg - Isd 特性" .Axes(xlCategory).HasTitle = True .Axes(xlCategory).AxisTitle.Characters.Text = "Vbg" .Axes(xlValue).HasTitle = True .Axes(xlValue).AxisTitle.Characters.Text = "Isd" .SeriesCollection(1).Trendlines.Add Type:=xlLinear, DisplayEquation:=True, name:="線形近似" .SeriesCollection(1).Trendlines(1).DataLabel.Select Selection.NumberFormat = "0.000E+00" End With With Sheets(CellNumber).Range("A1") .NumberFormat = "0.000E+00" .ColumnWidth = 11.5 End With Dim y As String y = Sheets(CellNumber).ChartObjects(1).Chart.SeriesCollection(1).Trendlines(1).DataLabel.Text Sheets(CellNumber).Range("A1").Value = y Dim con As String con = Left(Sheets(CellNumber).Range("A1"), 14) con = Right(con, 10) Sheets(CellNumber).Range("A1").Value = con Dim di As Single Columns("D:D").ColumnWidth = 11.5 Columns("D:D").NumberFormat = "0.000E+00" For t = 5 To 164 di = Cells(t + 1, "c") - Cells(t, "c") Cells(t, "D").Value = di / 0.5 Next End If Next ActiveWorkbook.SaveAs "D:\Desktopb\実験データ\sample1-" & BlockLineNumber & BlockColumnNumber, xlOpenXMLWorkbook ActiveWorkbook.Close SaveChanges:=True Next Next Application.SheetsInNewWorkbook = Pro End Sub うまく計算ができなかった点についても追記です。 近似曲線の傾きを利用したいので、上記のプログラムでは傾きを"A1"に書き込むようにしたつもりなのですが、 プログラムを実行したあとファイルをひらいてみると"A1"に値が出ているブックとそうでないブックが出てきてしまいます。
また、上記のプログラムはまだ途中段階で、
最終的には、別のブックに全ての近似曲線の傾き、及びデータの微分値を一覧にした形で出力しようと思っています。
あつかましいお願いですが、
これらを含めて良い解決策あるいはアドバイスがあれば教えて頂きたいです。
(こっくさん) 2015/09/03(木) 16:47
確かにワークブックの指定は省略していたので
Workbook(2)を指定して試してみました!
しかし残念ながら結果は変わらなかったです、、
ちなみにDoEventsは使い方がいまいちわからなかったのですが、
ここでの使い方は”DoEventsの次の行の動作をゆっくりと行わせる命令”
ということでよかったでしょうか?
(こっくさん) 2015/09/03(木) 18:36
(マナ) 2015/09/03(木) 19:12
>>ここでの使い方は”DoEventsの次の行の動作をゆっくりと行わせる命令”
あたらずとも遠からずです。実際には、処理を、ちょっと中休みというか、休憩して一服後、また開始と、こんなイメージです。 じゃぁ、どこに入れたらいいかとなると、そこはある程度【かん】ですね。
ちょっと気になるのは、やはり On Error Resume Next 等、エラートラップを多用しているところですね。 主として、ファイルが存在しなかった場合の対処でしょうけど、あまり感心しません。 開く前に、当該ファイルが存在するかどうか、これはいろんな方法がありますがVBA基本機能としてはDIR関数がありますので それをチェックして、有無によりロジック分岐をさせる。とくに、 Goto ラベル などは使わないようにされたらいかがですか? (エラーとは関係のない部分での GoTo もありますが、これも感心しませんね)
また、現在のコード、たとえば
On Error Resume Next Workbooks.OpenText "D:\Desktop\実験データ・・・ Sheets(1).Move After:=Workbooks(2).Sheets(CellNumber - 1)
というところがありますよね。 仮に、OpenTextで失敗したとする。でも、次のコードが実行される。これは、どのブックのSheet(1)かは別にして 確実に実行されますね。これは具合悪いでしょ?
さらに、このエラートラップのリセットは、そのあとの条件判定で、エラーが起こっていた場合、結局はリセットされていませんよね?
やはり、エラートラップは廃止しましょう。
あと、Workbooks(2) も気になります。PCの環境(というかエクセルの環境)により、ブックと認識されるファイルが 非表示で読みこまれている場合もあります。 ですから Workbooks(2) といっても、必ずしも、想定しているブックではない場合があります。 このような「環境依存」のコードではなく、きちんと目的のブックを指定されたほうがよろしいかと。
再現テストは残念ながら、読みこむべきブックのデータが、どのようなものか、わからないので、できません。 なので、ざっと眺めたレベルでのコメントです。
(β) 2015/09/03(木) 19:17
とりあえず、すべてのWorkbooks.OpenText の下に DoEvents を入れてみると、どうなりますか?
(β) 2015/09/03(木) 19:30
ちょっと本題からはそれますが。
>>最近になってVBAを知り勉強を始めました。 >>マクロを組んで実験データを一気に処理させようと思いちょっと長めなマクロを組んで実行してみました。
勉強を始めた段階であれば(に、かぎらずですが)長めのロジックを一挙にかかず、 1機能、1機能にわけて、1つずつ書いて、1つずつ確認する。1つがOKになれば、次のブロックを追加して確認する。
まずは、小さな単位で確実に機能するものを作り上げて、それらを結合していかれるほうが、結局は早いですよ。
(β) 2015/09/03(木) 19:34
>当方理系の学生です。 現役理系学生の親をやっているものとして、 >最近になってVBAを知り勉強を始めました。 最近がいつなのかによりますが、一年ぐらいを最近というなら、良くかけていると思いますよ。
ファイルI/Oに On Error Resume Nextを使うのは 私は、良いと思いますよ!! もっとも私なら、違うコーディングをしますが、まあでもよいでしょう。 ファイルI/Oのチェックで On Error 〜 よりよい方法は私は知らないので これを使うのはよいですが、 問題は使い方ですね!!
そしてもっとも気になるのは 既述ですが、GOTO文ですね!!
Goto 20 とGoto 30 これを削除して同じ意味になるコードに書き直してみてください。
新規ブックにて 以下のコードを実行してみてください。
Option Explicit Sub test() Dim a As Long On Error Resume Next MsgBox "ok1" GoTo 10 On Error GoTo 0 10: a = a / 0 MsgBox Erl & "でエラーになっているのにプログラムは止まらない" End Sub
プログラムのコードと実行した結果をよく調べてみてください。
これと同じ現象が提示されたコード内でも起きる可能性があります。
( ichinose) 2015/09/03(木) 20:33
マナさん
お返事ありがとうございます。
"グラフの概形を見る"かつ"傾きを調べる"事が目的でした。
グラフそのものは書けているのですが、傾きが指定した場所("A1")に出力できていない事が問題でした。
Slope関数というものは、はじめて知りました。
ざっと調べただけですが、まさに傾きを調べる関数ですね。
これを使えばうまくいくかもしれません。
今日はもう学校を出てしまったので明日ためしてみたいとおもいます。
>>βさん
お返事ありがとうございます。
DoEventsについて 分かりやすい解説をありがとうございます。
命令のイメージはつかめた気がします。
私の印象としてはグラフを操作する場合の負荷がおおきいのかな?という印象だったので、
With Sheets(CellNumber)ChartObjects(1).Chart
とある行の後ろにいくつかDoEventsをちりばめてみたのですがうまくいきませんでした。
今日は学校を出てしまったのですが、明日Opentxtの次の行にDoEventsをいれてみたいと思います。
エラートラップについて、 おっしゃる通り、データファイルがなかった場合の対応策としてOn Error
Resume Next を使っていました。
また、ご指摘の通り改めてプログラムを見直すと、自分でもよくないなあと思う使い方でした。
アドバイスのとおりDIR関数で、うまく解決できそうなので、実践してみたいと思います。
Workbooksでのブック指定について "ブックと認識される非表示のファイル"というものがあることをはじめて知りました。
自分で開くブックをきちんと管理しておけばこの指定の仕方でも良いだろうと思っていたのですが、よくなかったのですね。
改めて指定は厳密に行おうと思います。
長いプログラムの書き方について 恥ずかしながら、エクセルのVBAを知って1週間足らずの全くの初心者です。
今回書いたプログラムを書くにあたっては
"テキストファイルを開くマクロ"
"グラフを書くマクロ"
"保存をするマクロ"
といった具合に小さなマクロを作り、それぞれの動作が正確に行われていることを確認しました。
それらを1つずつ繋げて作ったのが今回のプログラムになります。
個別ではちゃんと動いていたのに繋げたとたんうまく動かなくなってしまったので、失敗の理由がわからず途方にくれていました。
たくさんのアドバイスをありがとうございます。
明日の結果はまだどうなるかわからないのですが、こちらご報告させていただきたいと思います。
もしお時間が許せばまたアドバイスをいただけるとうれしいです。
(こっくさん) 2015/09/03(木) 20:41
ichinoeさん
お返事ありがとうございます。
お誉めいただきうれしいです。
VBAは勉強を始めて1週間ほどです。
もともとC言語は教養として授業で教わっていたので、VBAもここまではわりとすんなりと来れました。
エラートラップについて、 エラーの回避としてネットで検索して出てきた命令文がOnErrorGotoでした。
うまく動いていたのでそのまま使っていたのですが、今回はβさんのアドバイスにあったDIR関数でもうまく処理ができるようなので、そちらもためしてみたいと思います。
Gotoの使い方について 頂いたコードがなんなのかコードをみただけでは、私にはわからなかったので、実際に動かしてみようと思います。
ただ今日は学校を出てしまったので明日実践してみたいと思います。
(こっくさん) 2015/09/03(木) 20:58
特定のファイルからデータを読み込む処理をしてくれるOpentextメソッド、 想定されるエラーは、何もファイルが存在しないというエラーだけではありません。 他のエラーもありますし、想定外のエラーだって起こるかもしれません。 そのようなエラーを拾ってくれるOn Error 〜はプログラムの完成度を高めるという観点からだと ファイルをオープンするという処理にははずせないステートメントです。 もう長いことVBAを含めたいわゆるBasicと呼ばれる言語でプログミングをしてきましたが、 この On Error 〜 ステートメントを書かない商品はなかったと思います。
ファイルI/Oに関しては、On Error 〜ステートメントは 必要不可欠 ということは 覚えておいてください。
今回は 使い方が問題なだけです。
ただ、今回のこっくさんの不具合を発見するための手段として、On Error 〜ステートメントを外してみる (代わりにDir関数で対応する)という試みは やる価値はあるかもしれません。
これによりもしかしたら・・ですが、私が提示したコードの意味もわかっていただけるかもしれません。
でも不具合がみつかり、修正し、完成されたコードには On Error 〜ステートメントは必要ですよ!!
>Gotoの使い方について 頂いたコードがなんなのか
提示したコードはGotoの使い方でなく Goto文の弊害です。 Goto文は使わなくてもプログラムは作れます。
Goto文は使わないという方針でプログラミングを考えてください。
( ichinose) 2015/09/04(金) 05:39
>>でも不具合がみつかり、修正し、完成されたコードには On Error 〜ステートメントは必要ですよ!!
ichinose大師匠のご見解ですが、あえて反論します。 実際には、コメントは
>>この On Error 〜 ステートメントを書かない商品はなかったと思います。
「商品」ととらえておられるご発言で、商品としては、後述のように、(ものによっては)理解していますが 基本的には、むやみやたらの エラートラップ(バイパス)は使うべきではないと考えています。
確かに、ファイルそのものは存在するけど、様々な原因で読めない場合もあります。 だけど、それを言い出せば、エクセルの世界です。たとえばセルにエラー値が(計算式の結果だけではなく 外部データのコピペ、あるいは何かしらの障害も含めて)入っている場合があります。 それを考えると、そのセルの参照にもエラートラップが必要になるという理屈になります。
等々、エクセルの世界ですから、あれも、これも エラーの可能性を含みます。その対処をするとなると もう面倒だからと言って、(β) 2015/09/03(木) 19:17 で、ちょっとふれましたが、先頭に1行、On Error Resume Next と書くという 本末転倒の発想を持つ人もでてくるわけです。
ましてや、今回のテーマは、(こっくさん) ご自身が、自分で作業するためのコードです。 ここでエラーになった場合、まず、連結して作り上げたファイルフルパス文字列が正しいのかどうか そこの検証で頭を悩ませます。DIR等でチェックしておけば、そこは、デバッグ作業からはずすことができるわけです。 また DIRで見つからなければ、今回の場合は ループ制御のインデックスですけど、それを組み合わせたものが悪い、 つまり、ファイルが読める読めない、という問題ではなく、ループ制御インデックスの扱いのバグという切り分けができるわけです。
「商品」としての性格を持つコードについては、昔、ベータも、そういった仕事に携わっていましたから理解できます。 これは、エラーを回避するという意味合いよりも、 ・エラーが発生した場合に、インタラクティブなプログラム実行環境では、だいたい、いわゆる「デバッグ画面」がでる。 そこで、わけのわからないエンドユーザに、めちゃめちゃなことをされると、リカバリーが大変になる。 たとえば、そこで中断してくれず、先に進めて、またエラー、そのうちに、エラーにはならず(おかしな状態を踏まえた)ノーマルエンド となり 後日、データがめちゃめちゃになってクレームが入る。もう、何が原因かがわからなくなる。 ・あるいは、処理中断すると、エンドユーザから保守窓口に、緊急対応しろ!! という連絡が来る。 これを、エラーートラップで、「予期しないエラーが発生しました。これこれこれの情報を受付デスクまでメールで連絡願います」 なんてメッセージを出しておくと、結構、「クレーム」にはならず「連絡」になるケースがあり、また 「今すぐ」ではなく、「まぁ、待とうか」という気持ちになるケースがあると、これはベンダサイドの悪知恵ですけど。
(β) 2015/09/04(金) 07:10
>むやみやたらの エラートラップ(バイパス)は使うべきではないと考えています。 それは、同感ですが・・・。 そのむやみにの 中身が違うのでしょうね!!
On Errorに関しては、記述どおりの意見です。
今回は、On Error 〜はずしてバグを探るという方法には、賛成です。
この方法で バグ発見をすることを優先させましょう ご自分で努力されている学生さんにみえるので、 バグ発見を遅らせたくはないので・・・。
この事では 何度か意見交換をしてきた経験があります。 私が近い内に別スレッドを立てますのでそちらで意見交換させてください。
( ichinose) 2015/09/04(金) 08:09
現在のコードは
sample1-12-1.txt〜sample1-89-4.txt の256テキストファイルを処理し、
sample1-12.xlsx〜sample1-89.xlsxの64ブックを作成するコードになっているようですが、
Workbooks.OpenTextでエラーになる場合は、
"No Data" & CellNumber
というシートを作り、セルA1に×をセット。
エラーにならない場合は、読み込んだテキストデータをコピー(Moveになっている)して
CellNumber
というシート名にし、Range("B5:C165")にグラフを作成し、
セルA1に
Sheets(CellNumber).ChartObjects(1).Chart.SeriesCollection(1).Trendlines(1).DataLabel.Text をセットする。
その他の書式等の処理も有りますが全体的にはこんな感じでしょうか?
(ウッシ) 2015/09/04(金) 08:58
こんな感じで、
Sub test()
Dim Pro As Integer Dim BlockLineNumber As Integer Dim BlockColumnNumber As Integer Dim CellNumber As Integer Dim t As Long Dim tBk As Workbook Dim s As Workbook Dim di As Single
Pro = Application.SheetsInNewWorkbook Application.SheetsInNewWorkbook = 1
' Application.ScreenUpdating = False
On Error GoTo Err_Line
For BlockLineNumber = 1 To 8 For BlockColumnNumber = 2 To 9 Set tBk = Workbooks.Add For CellNumber = 1 To 4 Workbooks.OpenText "D:\Desktop\実験データ\sample1-" & BlockLineNumber & BlockColumnNumber & "-" & CellNumber & ".txt", DataType:=xlDelimited, Space:=True Set s = ActiveWorkbook If Err.Number <> 0 Then If CellNumber = 1 Then tBk.Sheets(1).Name = "No Data" & CellNumber Else tBk.Worksheets.Add After:=tBk.Sheets(CellNumber - 1) tBk.Sheets(CellNumber).Name = "No Data" & CellNumber End If With tBk.Sheets("No Data" & CellNumber) .Columns("A:A").ColumnWidth = 30 .Rows("1:1").RowHeight = 120.75 With .Range("A1") .Value = "×" .Font.Color = -16776961 .Font.Size = 50 End With End With Else If CellNumber = 1 Then s.Sheets(1).Move After:=tBk.Sheets(1) Application.DisplayAlerts = False tBk.Sheets(1).Delete Application.DisplayAlerts = True Else s.Sheets(1).Move After:=tBk.Sheets(CellNumber - 1) End If
With tBk.Sheets(CellNumber) With .ChartObjects.Add(230, 50, 300, 200).Chart .ChartType = xlXYScatterSmoothNoMarkers .SetSourceData Source:=.Range("B5:C165") End With With .ChartObjects(1).Chart .HasTitle = True .ChartTitle.Characters.Text = BlockLineNumber & BlockColumnNumber & "-" & CellNumber & "の Vbg - Isd 特性" .Axes(xlCategory).HasTitle = True .Axes(xlCategory).AxisTitle.Characters.Text = "Vbg" .Axes(xlValue).HasTitle = True .Axes(xlValue).AxisTitle.Characters.Text = "Isd" .SeriesCollection(1).Trendlines.Add Type:=xlLinear, DisplayEquation:=True, Name:="線形近似" .SeriesCollection(1).Trendlines(1).DataLabel.Select Selection.NumberFormat = "0.000E+00" End With With .Range("A1") .NumberFormat = "0.000E+00" .ColumnWidth = 11.5 End With
.Range("A1").Value = _ tBk.Sheets(CellNumber).ChartObjects(1).Chart.SeriesCollection(1).Trendlines(1).DataLabel.Text
.Range("A1").Value = Right(Left(.Range("A1"), 14), 10)
.Columns("D:D").ColumnWidth = 11.5 .Columns("D:D").NumberFormat = "0.000E+00" For t = 5 To 164 di = .Cells(t + 1, "c") - .Cells(t, "c") .Cells(t, "D").Value = di / 0.5 Next End With End If Next tBk.SaveAs "C:\Desktopb\実験データ\sample1-" & BlockLineNumber & BlockColumnNumber, xlOpenXMLWorkbook tBk.Close SaveChanges:=True Next Next ' Application.ScreenUpdating = True Application.SheetsInNewWorkbook = Pro Exit Sub Err_Line: MsgBox Err.Description Resume Next End Sub
エラーになった都度、内容を確認してデバッグしていくといいと思います。
(ウッシ) 2015/09/04(金) 09:47
みなさんに頂いたアドバイスをもとに以下のようにプログラムを組んでみました
Sub 一括解析改良版()
' Application.ScreenUpdating = False
Dim FileName As String
Dim CellNumber As Integer
Dim BookName As String
Dim BlockLineNumber As Integer
Dim BlockColumnNumber As Integer
Dim Pro As Integer
Dim SheetsName As String
Dim NoDataName As String
Dim con As String
Dim di As Single
Dim y As String
Dim t As Integer
Pro = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
'各ブロックごとに処理
For BlockLineNumber = 1 To 8 For BlockColumnNumber = 2 To 9
'STEP1_データを1ブロックぶん開く
'1~4番セルのデータを開きブックを1つにまとめるて名前を付けて保存する。 BookName = "sample1-" & BlockLineNumber & BlockColumnNumber For CellNumber = 1 To 4 FileName = Dir("D:\Desktop\実験データ\" & BookName & "-" & CellNumber & ".txt") If CellNumber = 1 Then If FileName = BookName & "-" & CellNumber & ".TXT" Then 'On Error Resume Next Workbooks.OpenText "D:\Desktop\実験データ\" & BookName & "-" & CellNumber & ".txt", DataType:=xlDelimited, Space:=True DoEvents Else Workbooks.Add.Sheets(1).name = "No Data" & CellNumber End If ActiveWorkbook.SaveAs "D:\Desktop\実験データ\" & BookName, xlOpenXMLWorkbook
Else If FileName = BookName & "-" & CellNumber & ".TXT" Then 'On Error Resume Next Workbooks.OpenText "D:\Desktop\実験データ\" & BookName & "-" & CellNumber & ".txt", DataType:=xlDelimited, Space:=True DoEvents Sheets(BookName & "-" & CellNumber).Move After:=Workbooks(BookName).Sheets(CellNumber - 1) Else Worksheets.Add After:=Workbooks(BookName).Sheets(CellNumber - 1) Workbooks(BookName).Sheets(CellNumber).name = "No Data" & CellNumber End If End If Next
'STEP2_各シートにグラフを作成
For CellNumber = 1 To 4 'NoDataへの対処 SheetsName = Sheets(CellNumber).name NoDataName = "No Data" & CellNumber If SheetsName = NoDataName Then Columns("A:A").ColumnWidth = 30 Rows("1:1").RowHeight = 120.75 With Sheets(CellNumber).Range("A1") .Value = "×" .Font.Color = -16776961 .Font.Size = 50 End With
Else 'グラフ作製 With Sheets(CellNumber).ChartObjects.Add(230, 50, 300, 200).Chart .ChartType = xlXYScatterSmoothNoMarkers .SetSourceData Source:=Sheets(CellNumber).Range("B5:C165") DoEvents End With
With Sheets(CellNumber).ChartObjects(1).Chart .HasTitle = True .ChartTitle.Characters.Text = BlockLineNumber & BlockColumnNumber & "-" & CellNumber & "の Vbg - Isd 特性" .Axes(xlCategory).HasTitle = True .Axes(xlCategory).AxisTitle.Characters.Text = "Vbg" .Axes(xlValue).HasTitle = True .Axes(xlValue).AxisTitle.Characters.Text = "Isd" DoEvents '近似曲線の追加 .SeriesCollection(1).Trendlines.Add Type:=xlLinear, DisplayEquation:=True, name:="線形近似" DoEvents .SeriesCollection(1).Trendlines(1).DataLabel.Select DoEvents Selection.NumberFormat = "0.000E+00" DoEvents End With
'近似曲線の傾きの書き出し With Workbooks(BookName).Sheets(CellNumber).Range("A1") .NumberFormat = "0.000E+00" .ColumnWidth = 11.5 End With DoEvents y = Workbooks(BookName).Sheets(CellNumber).ChartObjects(1).Chart.SeriesCollection(1).Trendlines(1).DataLabel.Text Workbooks(BookName).Sheets(CellNumber).Range("A1").Value = y DoEvents con = Left(Sheets(CellNumber).Range("A1"), 14) con = Right(con, 10) Workbooks(BookName).Sheets(CellNumber).Range("A1").Value = con
'Slopeを使った傾きの書き出し With Workbooks(BookName).Sheets(CellNumber).Range("B1") .NumberFormat = "0.000E+00" .ColumnWidth = 11.5 .Value = Application.WorksheetFunction.Slope(Workbooks(BookName).Sheets(CellNumber).Range("C5:C165"), Workbooks(BookName).Sheets(CellNumber).Range("B5:B165")) End With
'微分操作 Columns("D:D").ColumnWidth = 11.5 Columns("D:D").NumberFormat = "0.000E+00" For t = 5 To 164 di = Cells(t + 1, "c") - Cells(t, "c") Cells(t, "D").Value = di / 0.5 Next End If DoEvents Next Workbooks(BookName).Close SaveChanges:=True Next Next ' Application.ScreenUpdating = True Application.SheetsInNewWorkbook = Pro End Sub
結果から報告させていただくと、改良したプログラムを動作させても以前のままと変わらず、すべてのブックの"A1"に近似曲線の傾きを表示させることはできませんでした。
ただし、SLOPE関数で"B1"に傾きを表示させることはできました。
近似曲線の傾きから表示できないのはまだ納得がいっていませんが、1つの目的であった傾きの表示には成功したので、Slope関数を用いて解析プログラムを利用したいと思います。
たくさんのアドバイスをありがとうございました。
今後もVBAについてたくさん勉強していこうと思うので、またわからないことがあったとき、ここに書き込みに来ることもあると思うのでその時はよろしくお願いします。
また、ほかにも試みたこと、およびその結果も御報告させていただきます
・Application.ScreenUpdatingの有効、無効によらず結果は変わりませんでした。
・On Error Resume Nextの有効、無効によらず結果は変わりませんでした。
・DoEvents上記のプログラムにもあるように様々なところにちりばめてみましたが結果は変わりませんでした。
またichinoseさんに頂いたコードですが、以下の2つのコードを実行してみました。
Option Explicit
Sub test1() Dim a As Long On Error Resume Next MsgBox "ok1" On Error GoTo 0 a = a / 0 MsgBox Erl & "でエラーになっているのにプログラムは止まらない" End Sub
Option Explicit Sub test2() Dim a As Long On Error Resume Next MsgBox "ok1" GoTo 10 On Error GoTo 0 10: a = a / 0 MsgBox Erl & "でエラーになっているのにプログラムは止まらない" End Sub
Option Explicit
test1ではエラーメッセージが表示されるのに対して、test2では「10でエラーになっているのにプログラムは止まらない」と表示されました。
そこで以下のようなプログラムも組んでみました。
Sub test3() Dim a As Long On Error Resume Next MsgBox "ok1" GoTo 10 10: On Error GoTo 0 a = a / 0 MsgBox Erl & "でエラーになっているのにプログラムは止まらない" End Sub
このプログラム結果はエラーになりました。
このことからGoTo文の弊害とは
"GoTo文を用いてOn Error Goto 0をよけてしまうと以降で想定していないエラーが発生しても何事もなかったかのようにプログラムが進んでしまうので注意しなければいけない"
ということでよかったでしょうか?
(これだと"エラートラップではGotoを使わないほうがいい"という結論になってしまうので、ichinoseさんがおっしゃりたかったこととは異なっているかもしれませんが、、)
ウッシさんに頂いたプログラムも動作させてみたのですが、ポップアップしたメッセージウィンドウをうまく消せなかったので2回目以降は動かすのが怖くて、申し訳ないと思いつつもデバックもしないままになっております。
ごめんなさい、、
もう少しVBAに詳しくなってからデバックに挑戦したいと思います。
(こっくさん) 2015/09/04(金) 18:19
>On Error Goto 0をよけてしまうと以降で想定していないエラーが発生しても何事もなかったかのようにプログラムが進んでしまうので注意しなければいけない" 弊害と申し上げたのはこのことです。
>エラートラップではGotoを使わないほうがいい"という結論 なるほど、でも私が申し上げたいのは、何であれ GOTO文は使わない という結論だったのです。
この掲示板でも読みにくいGOTO文を使った例は数年に一度ぐらいは見かけます。 逆に言えば、それほど、Goto文を使わないコードが市民権を得ていることになります。 何十年も前に提唱された構造化プログラミングの考え方が今も受け継がれているのだと思います。
プログラムの流れは、順構造、分岐構造 繰り返し構造 の三構造で成り立ち、 これは、GOTO文を使わなくても実現できる、逆にGOTO文を使うとロジックが理解しにくくなる。
実際には、構造化プログラミングで検索したりしてみてください。もっと詳しく書かれているサイトがあると思いますし、これを実現する考え方を記述した書物もあると思います。
実は、今回の件は、普段GOTO文を見慣れていない私は 最初気が付きませんでした。
私は、コード全体を精査しているわけではありませんが、on error goto 0 を何気に飛ばしているので
>For CellNumber = 1 To 4 > Dim SheetsName As String > Dim NoDataName As String > SheetsName = Sheets(CellNumber).name 以降続く
条件によっては、ここがエラーで止まらない場合があるので そこに原因があるかもしれない と思い、同様のコード例を提示しました。 今回は、On Errorをはずして結果が変わらないとなると、 原因はまだ突き止められていないようですが。
Gotoを使わなければこのようなミスも少ないと思いますよ。
繰り返しますが、 >エラートラップではGotoを使わないほうがいい"という結論 ではなく、Goto文を使わないコーディングをする です。
エラートラップの件とは 切り離してください。
これはこれ、あれはあれです。
私がGoto文を使ったのは、先のプログラムの流れの 分岐構造、繰り返し構造 を構築するのに Goto文を使わないと実現できない文法になっていた言語を使っていた時だけです。 (N88Basic アセンブラ Fortran77)
VBAは、Goto文なしでもコードは書けます。
Goto文論争を行っているサイトをちょっとまえまでよく見かけました。 (Goto賛成・反対論争です)
確か熟練者の中には、わかりやすくGoto文を使う方もいます。
が、プログラミングを始めて間もないのなら、まずは、Goto文なしでコードを書くことから 始めるほうが良いですよ!!
本題ですが、今度は 現象が再現する簡単な入力データ例を提示されてみては いかがですか?
( ichinose) 2015/09/05(土) 08:53
(マナ) 2015/09/05(土) 10:02
他板ですが、これも同じ原因かも。 http://excelfactory.net/excelboard/excelvba/excel.cgi?mode=all&namber=171347&rev=0
・データはRange("B5:C165")に適当なものを用意してください。 ・★の行によっては、A1セルに回帰式が表示されないことがあります。
Sub test() Dim ws As Worksheet Dim cht As Chart Dim ser As SeriesCollection Dim trd As Trendline
For Each ws In Worksheets ws.Activate '★ ' ActiveWindow.ScrollRow = 100 '★
With ws.ChartObjects.Add(230, 50, 300, 200).Chart .ChartType = xlXYScatterSmoothNoMarkers .SetSourceData Source:=ws.Range("B5:C165")
Set trd = .SeriesCollection(1).Trendlines.Add( _ Type:=xlLinear, _ DisplayEquation:=True)
Application.Wait Now + TimeValue("0:00:01") '★
ws.Range("A1").Value = trd.DataLabel.Text
' ActiveWindow.ScrollRow = 1 '★
End With Next
End Sub
(マナ) 2015/09/05(土) 11:20
ichinoseさん
確かに今回のプログラムでは、実際にGotoを使わなくても同様に動作するプログラムを組むことができました。
また以前のプログラムを見てみると、Gotoを使って行を移動してしまう読みづらいプログラムだな、と思ったのでこれからは使わずにプログラムを組むように心がけたいと思います。
同じ現象の再現は取れてはいないのですが、、
Sub txtファイル作製()
Dim a As Single
Dim CN As Integer
Dim BookName As String
Dim BLN As Integer
Dim BCN As Integer
Dim Pro As Integer
Dim X As Single
Dim y As Single
Pro = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
PlaceOfData = "D:\Desktop\VBA検証\"
For BLN = 1 To 8 For BCN = 2 To 9 BookName = BLN & BCN
For CN = 1 To 4 With Workbooks.Add .Sheets(1).name = BookName & "_" & CN ActiveWorkbook.SaveAs PlaceOfData & BookName & "_" & CN, xlText a = (-1) * (Int(Rnd * 100)) / 1000000 For X = 1 To 160 Workbooks(BookName & "_" & CN).Sheets(BookName & "_" & CN).Range("A" & X).Value = X y = a * X + 0.003 + Rnd / 50000 Workbooks(BookName & "_" & CN).Sheets(BookName & "_" & CN).Range("B" & X).Value = y Next Workbooks(BookName & "_" & CN).Close SaveChanges:=True End With Next
Next Next Application.SheetsInNewWorkbook = Pro
End Sub
これで似たようなファイルが作れます。
マナさん 頂いたURLの現象と私のプログラムで起きた現象が同一のものなのかはいまいちわからなかったのですが、
"都度シートをアクティブにする"というのをプログラムに組み込んでみたところ近似曲線の傾きを出力することができました。
原因はまだ私もわかりませんが、取りあえずですが、当初の狙いのままのプログラムが動くようになったのですっきりした気持ちです。
ありがとうございます。
(こっくさん) 2015/09/07(月) 20:49
以前、同種と思われる質問がありました。
『VBAでグラフの自動更新を行うが凡例が正しく設定されない』(チャッコロ) [[20140428175241]]
相違点は、今回が、 Application.ScreenUpdating = False がコメントアウトされていること、 都度シートをアクティブにすると成功したこと
同じなのは chart関連で、ステップ実行だとうまく行くこと
ユーザーには知らされていない「描画に関する仕様」に基づく現象、と云う気がします。
(半平太) 2015/09/18(金) 09:10
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.