1 :
デフォルトの名無しさん :
2010/07/25(日) 17:18:32
いちおつ
4 :
デフォルトの名無しさん :2010/07/25(日) 23:26:18
>>4 フォームの開くボタンでブック選ばせて開いて
ユーザーはその開いたブックのシート適当にアクティブして
先ほどのフォームの実行ボタンでアクティブなシートに処理
閉じるボタンで開いたブックを閉じる
という3つボタンのあるフォームの考えたんだけど
なんかだめかな?
該当ブックのシート名を全て取得し、選択ダイアログ等にするのは微妙です ってなに?これが一番いい方法だと思うが・・
>>4 前スレ
>>996 の意味が理解できないんでパスするけど
>>991 ,994 を読む限り
ExcelAにあるVBAで ExcelBのイベント(各シートに切替えた時とか)を処理するには
クラスモジュール使ってイベント処理すれぱできるんだけど
少々難易度が高いかも(ポイントを掴めばそう難しくはないんだけど)
9 :
8 :2010/07/26(月) 00:33:01
ちょっと訂正 ExcelA → BookA ExcelB → BookB に読み替えて
10 :
デフォルトの名無しさん :2010/07/26(月) 07:50:26
>>5 ユーザ側で3度もボタン押下させるのは厳しいです
閉じるボタンを省いても2回ボタン押下…
>>8-9 の方法で厳しいようであれば
>>5 さんの方法で行くと思います
有難うございました
>>7 シートの中身をユーザ側で見てから、実行するシートを選ぶようにするためです
選択ダイアログではシートの中身をユーザが確認出来ないので…
>>8-9 シート切替時をトリガにする事が出来るんですね?
ありがとうございます
調べてみます
前スレ
>>992 サンクス
結局Excelのバージョンだけが関係するのか、それとも昔のFormatみたいにOSが関係するのか分らなかったな。
なんかよくわからんけど、コード断片貼っておく。 Thisworkbookのコード。 Private WithEvents MyBook As Workbook Sub foo() Set MyBook = Workbooks.Open("C:\Book1.xls") End Sub Private Sub MyBook_SheetActivate(ByVal Sh As Object) MsgBox Sh.Name & "が選択されました" End Sub VBEのオブジェクトでMyBookを選択すれば、補足できるイベントがプロシージャに表示される。
witheventsって知らない人は全く知らないからなぁ(あたりまえ)
俺なんか知らないこと以外全部知ってるぜ
知ってなくちゃいけないことを知らないけど何か問題ですかね!
16 :
8 :2010/07/26(月) 19:02:47
>>12 自分は全部クラスモジュール作ってたけど
こうゆうやり方もあるのね すごく勉強になった
さすがです
17 :
7 :2010/07/27(火) 01:47:12
>選択ダイアログではシートの中身をユーザが確認出来ないので… 普通に内容を確認して現在のアクティブシートに対して処理をするなら ツールボタンを用意しておいてマクロの入ったブックのその中のマクロを '(ブックのフルパス).xls'!(その中のマクロ) にしておけばそのボタン押すだけでアクティブシートに対して処理できます マクロのブックが読み込まれていなければ当然マクロを有効にするか 聞いてくるけどこの方法が操作回数も少なくていいと思う ツールボタン押さない限り普通の閲覧と一緒
>>17 ツールボタンからのマクロ実行は盲点でした!
確かにUI的にスマートになるし全然ありですね
しかし、色々と手があるものですね
勉強になります
有難うございました
質問です シート内にあるオブジェクトとシェイプ内にある文字を取得する方法は分かったのですが、 グループ化されたシェイプでエラーになります 最初にシート内の全てのシェイプんグループ解除すれば上手く機能するんですが、 元々グループ化されていたシェイプに対して再グループ化する事は出来るのでしょうか? また、グループシェイプか否かを判定する方法はあるのでしょうか?
VBA初心者なんですが Sub 検索() Worksheets("Sheet2").Activate For i = 1 To 1000 Worksheets("Sheet2").Range("B" & i).Select If Selection = "№1" Then Worksheets("Sheet2").Range("B" & i).Copy Worksheets("Sheet2").Range("H100").PasteSpecial Worksheets("Sheet2").Range("D" & i).Copy Worksheets("Sheet2").Range("H101").PasteSpecial Worksheets("Sheet2").Range("C" & i).Copy Worksheets("Sheet2").Range("H102").PasteSpecial Worksheets("Sheet2").Range("E" & i).Copy Worksheets("Sheet2").Range("H103").PasteSpecial End If Next End Sub これでB列の中から№1という文字列を検索してその行のB,D,C,E列のをH100,101,102,103にコピー&ペーストしたいのですが №1を無視して1000までいってしまいます どうすればいいですか?
>>20 無視はしていないと思うけど
№1 という文字列が見つかったらコピペしてそれ以上は検索しないなら
コピペ後に
Exit For
を入れる
できました ありがとうございました
23 :
デフォルトの名無しさん :2010/07/28(水) 17:00:29
Excel 2003で 問題が発生したため、microsoft office excel を終了します。 ご不便をおかけして申し訳ありません。 というエラーが出て困っています。 原因は何なのでしょうか。 VBAのUserForm上のオブジェクトにアクセスしようとすると上記のエラーが発生するようです。 発生条件としては、Visual Basic Editorを開いているときはエラーは発生しません。 VBAソースを修正して保存して閉じ、その後開いた場合はエラーは発生しません。 Visual Basic Editorを開かずにExcel上で上書き保存した場合、 再度開いたときに、エラーが発生します。 気になるのは、UserFormに置いているオブジェクトの数が 相当数あるのですが、制限のようなものがあるのでしょうか。 テキストボックスを300個程度と、ラベルが600個程度、マルチページで10ページほどに 分けて配置しています。 原因と対策がわかれば教えてください。
今のファイル形式だと、マクロ対応ブックとそうじゃないのがあるのな なんで書いたマクロが消えるんだよハゲ!って思ってたら、 マクロ対応した形式で保存しておかなければならなかったでござる
>>25 保存する時に「このまま保存するとマクロが消えるよ」って警告メッセージ出るだろ
よく読まずにOK押すお前が悪い
23です。
>>25 Excel2003では、どちらもxlsなので普通に保存できてしまいます。
結果ですが、
ファイルの保存形式を「Microsoft Excel 97-Excel 2003 および 5.0/95ブック(*.xls)」
としていたのがダメだったようです。
「Microsoft Excelブック(*.xls)」
にしたら大丈夫なようです。
ありがとうございました。
Excel2000で質問です。 対象セル(特定の1セル)がブランクかどうか判定したいと思い、 .SpecialCells(xlCellTypeBlanks) を利用したのですが、結局うまく機能しませんでした。 SpecialCells(xlCellTypeBlanks)が一体どういう動きをしているのか教えていただけませんか?
29 :
28 :2010/07/30(金) 21:12:16
具体的に試した内容は以下の通りです。 A B 1 (Blank) hoge1 2 (Blank) hoge2 3 (Blank) hoge3 4 (Blank) hoge4 5 (Blank)(Blank) ※これ以外のセルも全てブランクです Range("B5").SpecialCells(xlCellTypeBlanks).Select とすると、A1:A4のエリアを1つ持つRangeオブジェクトが返ってきます。 期待していたのは「B5というエリア内の全てのBlankセルを持つRangeオブジェクト」なので、 「Countが1でB5だけを持つRangeオブジェクト」が返って来る予定だったのですが全然違いました。 Range("B5:B5").SpecialCells(xlCellTypeBlanks).Select Range("B4").SpecialCells(xlCellTypeBlanks).Select Range("B4:B4").SpecialCells(xlCellTypeBlanks).Select もまったく同じ答えです。 Range("B4:B5").SpecialCells(xlCellTypeBlanks).Select こうすると実行時エラー1004(該当セルが見つかりません)が返ります。 よく、わかりません。
>>29 あまり詳しくないけどテストした限りでは
1)単一セルだと
その指定を無視して.UsedRange内のブランクセルを返している
2)セル範囲だと
指定したセル範囲内で かつ .UsedRange内のブランクセルを返している
ように見えるな(あくまで今回テストした状況では)
※ .UsedRange = ワークシートで使われたセル範囲
>Range("B5").SpecialCells(xlCellTypeBlanks).Select
>Range("B5:B5").SpecialCells(xlCellTypeBlanks).Select
>Range("B4").SpecialCells(xlCellTypeBlanks).Select
>Range("B4:B4").SpecialCells(xlCellTypeBlanks).Select
これは全て単一セルで 1)に該当
>Range("B4:B5").SpecialCells(xlCellTypeBlanks).Select
これは 2)に該当するけど
.UsedRange が [A1:B4] なら
[B4:B5]と[A1:B4]の両方に該当するセル範囲(つまり B4)に
ブランクセルは無いのでエラー
Excel2007なら指定したセル範囲内で かつ .A1~最後のセル内の空白セルだな。 UsedRange内じゃないようだ。 2003でも同じじゃなかったか?
>>28 判定したいだけなら、ワークシート関数のISBLANKで良い気がするけど・・・
Excelのマクロでファイルをダウンロードし、DLが失敗した場合はポップアップを出力させ、 正常にDLした場合はなにもさせないという処理をさせてます。 そのマクロを、タスクに登録したvbsファイルで実行しているんですが、 処理終了時にエクセルを閉じさせることができません。 試しにマクロ側でif文を設け正常にDLできた際にapplication.quitを実行させましたがvbs側でエラーが出てしまいました。 正常終了時はエラーもなくエクセルを終了させ、異常時はそのままポップアップを出力させるにはどうしたらいいでしょうか?
excel2003で、マクロを使って新しいシートを作りたいのですが、 その新しく作ったシートにマクロを入れたいのです。 マクロのコードを他のシートにコピーする又は最初からマクロを持ったシートを作ることは出来ますか?
>>34 テンプレートを使用するってのはどうでしょうか
1)シートを 1 つだけ含むブックを作成しそのシートにマクロを記述しテンプレートとして保存
2)新規作成時にそのブックを使用する
Sheets.Add Type:="c:\temp\Book1.xlt", after:=Sheets(1)
※テンプレートとして保存しなくても xlsでも問題ないと思う
>>33 なんか色々とおかしい気がするんだが・・。
モジュールに書き込むコードがあったはず
vlookupって各キーにアイテムって一つしか登録できないですよね 引っ張ってきたいアイテム(列)が複数ある場合は毎回「キー登録、列変えてアイテム登録、検索」を 繰り返すしかないのでしょうか?
知人が仕事でVBAを使うらしく尋ねられたのですが、 自分はVB系はサッパリダメでアドバイスのしようが有りませんでした。 そのまま放り出すのもアレなのでせめて適当な書籍を紹介してあげたいのですが 何かありませんでしょうか プログラム未経験者がとっかかりになるようなレベルでお願いします
41 :
33 :2010/08/02(月) 10:35:08
ファイルのDL自体はFTPで取得し、その後ローカルにファイルが存在するかをif文で判定させて 判定結果によってポップアップorエクセルを閉じるという処理をしたいと考えてます。 その処理をタスクで実行させるために、マクロを実行させるvbsファイルを作成し、タスク登録してます。 コードは今手元にないので一部しか覚えてないです。。 ■■EXCELのマクロ■■ sub ○○ <ファイル取得処理> if ファイルが存在しない then ポップアップ出力 else Application.Quit Windows("Book1.xls").Close True end if end sub ■■VBS■■ すみません。全く覚えてないです。 しかし、マクロを実行させるコードしか書いておらず、 終わった後にエクセルを閉じる処理は記載してません。
>>40 本屋に行けばそれこそ入門書が山のようにある
10日でできるシリーズとか。
本人に大きい本屋に行かせて自分で選ばせなはれ
ループの回し方の質問です。 1行目がタイトルで2行目以降のデータ処理がしたくて Dim MyRng As Range Dim MyCell As Range Set MyRng = Range("A2", Range("A65536").End(xlUp)) For Each MyCell In MyRng '処理 Next としたときA2以下にデータがないときA1も対象になってしまいます。 For i = 2 To Range("A65536").End(xlUp).Row '処理 Next とすればデータがないときは何もしないで抜けますが、For Eachでも 何もしないで抜けるにはどうすればいいですか?
Set MyRng = Range("A2:A65536")
>>43 MyRng.Rowが2より小さかったら抜ければいいんだよ。
Sub foo()
Dim MyRng As Range
Dim rngTop As Range
Dim MyCell As Range
Set rngTop = Range("A2")
Set MyRng = Excel.Range(rngTop, Range("A" & Row.Count).End(xlUp))
If MyRng.Row < rngTop.Row Then Exit Sub
For Each MyCell In MyRng
Next
End Sub
そういえばどこぞのコメントの王様は行番号をこねくりまわしてたな。
>>44 おいおい、データのないセルまで処理するのかよ
>>45 のSet MyRngのとこは
Set MyRng = Excel.Range(rngTop, rngTop.EntireColumn.Cells(Rows.Count).End(xlUp))
としてもいいね。
47 :
43 :2010/08/03(火) 10:43:16
>>45-46 なるほど、行番号で比較とは思いもよりませんでした。
仕方ないのでA2:A65536をCountAで先に数えるのかなぁ思ってました。
>>44 はそのヒントですか?
お前らいつまで65536行しか使えないエクセル使ってるんだと
49 :
デフォルトの名無しさん :2010/08/03(火) 13:31:52
VBAのオブジェク名の変更をC#のようなデザインコードから エディットしたいのですが どこかにありませんか? プロパティ値から一個一個変更するのは手間がかかりますので
50 :
49 :2010/08/04(水) 02:15:35
追記としてバージョンは2003です
Outlook VBAの情報が少なくてよくつまずくんだが、Outlookもここでしつもんしてもいいの?
専用スレないし、スルーされても泣かないなら良いんじゃね? 分かる事なら答えるよ。
ならばWordVBAも話題もここで良いですか?
むしろ俺が聞きたいくらい
ほかに適切なスレが見当たらないからここで聞いてもいいと思うけど スレタイがExcelだから、答えられる人がここを見てるとは限らないよ
レファレンス調べるくらいなら出来るから聞くだけなら もし解答してくれる人が不在でスレ違いとか言われたら諦め
>レファレンス www
それを言うなら「マンキ」の方がさらに近い 日本語だと長音に一音節分の時間を当てるけど英語の発音ではあんまり語尾を長く伸ばさない
必死だなwww
で、ワードはいいのか?
VBAなら何でも良いんじゃね?VBSでも何でも良いと思うわ。 分かる事なら答えるし、分からない事なら無視するけど。 それで泣かないならじゃんじゃか質問しちゃいなよ。
HOGE = Range("A10:M129").Value とやってセルの一定の範囲を配列に突っ込んで、 配列上で後から空白行を削除しようとしてるんですが、 やりかたがわからないです・・・。 EntireRow.Deleteってのはセルでしか使えないんですかね?
なんか途中の要素を削除するってのはめんどくさそうですね・・・。
>>63 2次元配列に格納して、削除するのは1次元か?
そりゃ訳分からなくなるぞ。
どうやってループすればいいのかも分からん。
>>65 まさにそうなんです。
二次元配列として折角行列毎取り込んでメモリ上で扱えるんだから、
EXCELの行列みたいに扱えたらいいのになあ、と思ったんですが、そうもいかないようです。
最初からワークシート上で一行づつ逐次評価して行く方がレベルに合ってるかもですね。
また暇な時にでも調べてみます。
セル範囲の内容を保持しつつ、一部を書き換えるようなことはできますか? 具体的には、 A1~B2の2*2のセルに値「1」が入っているとします。 その中のB1の値を2に書き換え、C1~D2に転記するような感じです。 Sub 書き換え() Dim a Set a = Range("A1:B2") a(0, 1) = 2 'B1の値を2に置き換え Range("C1:D2") = a End Sub (注)もちろん、動きません。
>>67 こんなかんじかな?
a.Cells(1, 2).Value = 2
Range("C1:D2").Value = a.Value
又は
a(1, 2).Value = 2
Range("C1:D2").Value = a.Value
>>68 レスありです。
前スレだったかな?「Valueは規定値なので省略可」というのを見たため、
基本的にはずしてました。
ただ、元の「A1:B2」の値が変わってしまうのが問題です。
書き方が悪かったようです。
「A1:B2」の一部の値を書き換えたものを「C1:D2」へ転記です。
最初に「A1:B2」の値を「C1:D2」へ移して、「D1」の値を書き換えるという方法もあるのですが、
データが大量にあるため、配列に格納してメモリ内で処理し、最後に貼り付けようと思っています。
今現在は、
For i = 0 to 1
For j = 0 to 1
a(i, j) = Cells(i + 1, j + 1)
Next
Next
a(0, 1) = 2
と、全てループし、配列に格納しています。
70 :
68 :2010/08/13(金) 16:15:54
>>69 Sub 書き換え()
Dim a As Variant
a = Range("A1:B2").Value
a(1, 2) = 2
Range("C1:D2").Value = a
End Sub
ちなみに配列a のインデックスの最小値は 1
>>70 ありがとうございます。
思った通りの動作になりました。
If IsArray(OpenFileName) Then For i = 1 To UBound(OpenFileName) Workbooks.Open OpenFileName(i) OpneFile = ActiveWorkbook.Name SheetsCount = Workbooks(OpneFile).Worksheets.Count Next i Else このコードで OpneFile = ActiveWorkbook.Name SheetsCount = Workbooks(OpneFile).Worksheets.Count の部分を SheetsCount = Workbooks(OpenFileName(i)).Worksheets.Count にできませんかね? OpneFile = ActiveWorkbook.Name がとってもいやんなのです よろしくお願いします
>>72 "できませんかね?"じゃなくて実際にやってみたらどうなのよ
なにが"とってもいやんなのです"も分からんし
実際にやってみて希望通り動作しないなら
どうダメなのかも含めて質問しる
俺ならActiveWorkbookの部分を固定できるようにするな ActiveWorkbook、sheetは誤作動がこわい
>>72 ブックをopenする時にオブジェクト型変数にsetすれば良くなるんじゃない?
そうすりゃブック型変数をかっちりと指定出来るから誤作動も減るだろうし可読性も上がると思うよ。
76 :
デフォルトの名無しさん :2010/08/16(月) 14:29:09
各セルに 新,復,復w,復,新,復,新 のように並んでいる行の中から、復wを含むセルが左から何番目にあるのか (上記例なら3番目)を得ようとしています。 Sub match() Dim myRange As Range Set myRange = Worksheets("sheet1").Range(Cells(1, 1), Cells(1, 350)) 'Range("A1:IV1") Dim i As Long i = Application.WorksheetFunction.match("復w", myRange, 0) MsgBox (i) End Sub このとき、3行目で、コメントアウトしているA1形式だとうまくいくのですが、 R1C1形式にすると、実行時エラー'1004'が出てとまってしまいます。 R1C1形式でうまくいってほしいのですが、なにがまずのでしょうか。 よろしくお願いします。
77 :
デフォルトの名無しさん :2010/08/16(月) 18:23:40
Range("A10:X40").Value = "" このマクロを流すとNull文字が入ってしまいます 実際、マクロ流した後シートを開くとセルの中は空なんですがNull文字があると認識されます (該当セルに関係してる他のセル式の挙動が半角ブランクを入力した時と同じになる) これをクリア(無)するにはどうマクロを書いたら良いでしょうか?
empty
>>77 Range("A10:X40").ClearContents
>>76 原因は2つ考えられる
1)sheet1がアクティブになっていない
Worksheets("sheet1").Range(Cells(1, 1), Cells(1, 350))
これは
Worksheets("sheet1").Range(ActiveSheet.Cells(1, 1), ActiveSheet.Cells(1, 350))
と同じ意味である
Worksheets("sheet1").Range(Worksheets("sheet1").Cells(1, 1), Worksheets("sheet1").Cells(1, 350))
とすべきである(Withとか オブジェクト変数とかで 短く出来るけど)
2)実在するセル範囲ではない
IV1 なら Cells(1, 256) じゃない?
Cells(1, 350) だと 多分"ML1"(ちょっと自信ない)
になると思うけど
>>76 の環境では実在するセルなの?
80 :
76 :2010/08/16(月) 20:04:08
>>79 さん
ありがとうございました。原因2)のほうでした。
テキトーなことするとやはり失敗するものですね。
おっしゃるとおり、Cells(1, 256)なら成功し、
Cells(1, 257)にすると
>>76 の失敗症状になりました。
助かりました。
82 :
77 :2010/08/17(火) 08:51:01
>>79 ありがとうございました!
無事に解決できました
クリアする時はNull文字を考慮してクリアするように気をつけます
OLEObject使用時の種別判定についてお聞きしたいのですが 例えばシート内に ToggleButton CommandButton を配置した際にOLEObject(i)がどちらの種類のボタンか判定したいのですが どのような方法があるのでしょうか? 現在のところ If OLEObjects(i).name Like "ToggleButton*" Then で判定しているのですが他にもっといい方法があれば教えてください。
複数行選択したセルの値を一定間隔ごとに詰める処理をしています。 (n個残してm個削除の繰り返し) 例(注:実際は行方向ですがレスが長くなるので列方向で記載します) 1 2 3 4 5 6 7 8 9 10 n=1,m=1であれば 1 3 5 7 9 n=2,m=2であれば 1 2 5 6 9 10 です。 拙い知識で.Delete Shift:=xlUpを使って目的は達成しましたが 非常に遅くなっています。 もっと高速にしたいのですが、多分.Delete Shift:=xlUpではこれ以上 早く出来そうにありません。 他の方法があればヒントなり教えてください。 条件として選択範囲以降の行は上に詰めることでお願いします。 環境:WindowsXP Excel2003 宜しくお願いします。
>>84 適当だけど、
最初に削除対象の複数の行をすべて選択してから削除するとか
処理のあいだ、画面更新を抑止するとか
そういうのはやってる?
86 :
840 :2010/08/19(木) 09:47:17
>85 >最初に削除対象の複数の行をすべて選択してから削除するとか 対象個数が不定なんですがVBAで処理できるんでしょうか?
エクセルからのOLEObj制御は充実してないようだ VS入れて使うとかしかないんじゃないかしら 詳しい話はMSDNでググーれ
>>84 とびとびに削除ってのは遅いんだよ。
だから
>>85 の方法は駄目ね。
作業列と並び替えを使えばよい。
n=2,m=2であれば
作業列が仮にC列なら選択範囲の右のC列に全部1とでも書いておく
C1とC2を消す
C1:C4を選択して右下のフィルハンドルをダブルクリック
C列をキーにして並び替えれば作業列が1のデータが前に並ぶから、そこをまとめて削除すればよい
ようするにとびとび削除じゃなく、ひとかたまりを削除なり消去するのがコツだ
90 :
84 :2010/08/19(木) 13:43:11
>87 不定数のセルをどうやってselectするのですか? >89 レスありがとう。 試してみました。 多少は早くなっているようですが、作業列に並び替え用キーを入力す るのに時間が掛かってる・・・orz 気長にいろいろとトライしてみます。 ありがとうございました。
>>90 コンマで区切る
A1セル、C3セル、E列全体、5行目全体をSelectしたい時は
Range("A1,C3,E:E,5:5").Select
>>91 その区切る個数が不定だと言ってると思われ。
nとmわかるんだから セレクトは出来るんだろう どこまでループさせるかはいろいろあるだろうけど
>>90 暇だから試してみたけど、やっぱりソートしてから削除が圧倒的に速かった。
全行(65536)から偶数行だけ削除で、うちだと5秒くらい。
複数Rangeの一括削除は、以外に遅くて、対象が増えると一行毎に削除するより遅くなってる気がする。
ちなみに複数Rangeの選択はUnion()を使う。
それはうにおんのせいでわ
96 :
702 :2010/08/19(木) 16:27:23
>94 テストありがとうございました。 こちらではソートキーの設定だけでおよそ1sec/50行ほど掛かって しまいます。この作り方が悪いんでしょうね。 そのソートキーの作り方を教えていただけないでしょうか? 当方がテストしたのは下記です。 宜しくお願いします。 Sub test() n = 2 m = 2 myRows = Selection.Rows.Count myColumns = Selection.Columns.Count Selection.Resize(1, 1).Select myRow = Selection.Row myColumn = Selection.Column Columns(myColumn).Select Selection.Insert Shift:=xlToRight With Cells(myRow, myColumn) For i = 1 To myRows .Offset(i - 1, 0) = i If (i - 1) Mod (n + m) >= n Then _ .Offset(i - 1, 0) = i + myRows Next i End With End Sub
97 :
84 :2010/08/19(木) 16:28:08
>96は>84です。 名前欄間違えました(汗
>>96 なんでそんなに違うんだろう?
やり方はあまり変わらないと思うけど、一応試したの貼っておく。
Sub test5()
Dim i As Long
Dim n As Long
n = 65536
Debug.Print "= 5 ==== "
Debug.Print "start " & Now()
Application.ScreenUpdating = False
Cells(1, 1).EntireColumn.Insert
For i = 1 To n
If Cells(i, 1).Row Mod 2 = 0 Then
Cells(i, 1).Value = "x"
End If
Next
Debug.Print "sort " & Now()
Range(Cells(1, 1), Cells(n, 2)).Sort key1:=Cells(1, 1), order1:=xlDescending
Debug.Print "delete " & Now()
If Cells(1, 1) = "x" Then
Range(Cells(1, 1), Cells(Cells(1, 1).End(xlDown).Row, 2)).Delete shift:=xlShiftUp
End If
Debug.Print "delete work" & Now()
Cells(1, 1).EntireColumn.Delete
Application.ScreenUpdating = True
Debug.Print "end " & Now()
End Sub
99 :
84 :2010/08/19(木) 17:35:50
>98 ソースをありがとうございました。 試してみましたが・・・終わりません。 n=655にしたらstartからsortまでが30秒掛かりました。 何か違うところに原因がありそうです。 のんびり調べてみます。 ありがとうございました。
>>99 重い数式使ってるんじゃねーの?
最近はアホ回答者が平気で揮発性関数やら配列数式教えるからな。
その都度再計算してるんじゃねーかな。
根本的な解決策じゃないが試しに下の二つではさんでみたらどうなる?
Application.Calculation = xlCalculationManual
'記述
Application.Calculation = xlCalculationAutomatic
つか、重いって言ってる人間にUnion勧める奴は何なんだよ。 Unionなんてあんこ力士並の機敏性だぞ。
まてまて そう言うことならまずあんこ力士の機動力を測定しなければならんな
103 :
84 :2010/08/20(金) 14:52:12
>100 ご指摘の通り自動計算の問題でした。 ありがとうございました。
気軽にSQLを叩く方法は無いかのう…。 ADOで自分のシートに接続するとか、MS-Queryが普通なの?
うん(`・ω・´) それ以外あるのかな?・・・
>>104 VBAに直接記述してから読み込ませれば?
自作関数ってこと?
108 :
デフォルトの名無しさん :2010/08/21(土) 18:24:33
教えてください。 Wordのパスワードを解除できるようにしたいのですが、 .Password = "" 上記のように "" で上書きしようとしても、元のパスワードのまま変更することができません。 何か文字列を入れれば上書きされ、変更することはできるのですが… 説明が下手で申し訳ありませんが、どうにか方法がありましたら教えてください。
空文字入れても駄目なのか。 VbNullとか・・・ダメだよな、やっぱり。
そりゃ元のパスワードなしで解除できたらセキュリティホールすぎるだろ Word VBA のヘルプで検索したら↓が出てきた Document.Unprotect Password:=strPassword
ごめん ↑は文書の保護で別物っぽい
112 :
108 :2010/08/21(土) 23:24:41
レスありがとうございます。 元のパスワードは開く時に入力しています。 パスワードの変更はできるのですが、解除ができない状態です。 NULLも試してみましたが、空文字と同じでした…。
俺のワードだとパスワード削除したら出来るな ワードのパスワード変更は ツール→オプション→セキュリティ からだぞ
114 :
108 :2010/08/22(日) 00:05:42
こちらでもワード上で直接操作してパスワード削除すれば解除されます。 ワード上でマクロの記録も使ってみましたが、何も記録できませんでした。 もちろん自分でも調べたり色々試しているのですが行き詰っています。
115 :
108 :2010/08/22(日) 01:46:34
ありがとうございました。一応、解決…というか、どうにかなったので報告しておきます。 空文字を入力(PWを削除)した場合、上書き保存ができていなかったようです。 別名で保存後、元ファイルを削除、リネームという方法で上手くいきました。 なんだか回りくどくて不満ですが、妥協することにします。
116 :
デフォルトの名無しさん :2010/08/22(日) 12:57:22
スレ違いでしたらすみません 業務にて3ヶ月前よりVBAの作成、改修の業務をしております プログラムは未経験のためかなり苦労しておりますが頼りの先輩の辞職してしまったため1人でで対応しなくてはならない状況になってしまいました みなさんの上達方法と一人前になるためにかかる期間を教えていただけますでしょうか またよい研修がありましたら教えていただけると嬉しいです よろしくお願いします
記録する ところどころ変えてみる 本読む やりたい動作をリストアップして実際に書いて動かす 早ければ3日、遅くても20年くらいじゃね
答えが分かる質問だと 上から目線で横柄な態度で仰々しく答える。 答えが分からない質問だと なんだかんだと攻撃して 答えなくて済むようにしてその場を繕う。 あなた方はクソですね。 ァ ∧_∧ ァ,、 ,、'` ( ´∀`) ,、'` '` ( ⊃ ⊂) '`
>>116 一番の上達方法は、いかに検索が上手く出来るかだと思う。
入門書を1冊、上級者向けを1冊買って、しっかり読み解く。
それが出来たら、見よう見まねである程度のプログラミングは出来るようになると思うけど、
それからが本番だよ。
検索して、先人の作ったプログラムを解釈して行く。
決してコピペで済ませない。面倒でも自分で手打ちする事。
分からなくなったら上級者向けの本を読みなおす。
>>118 > 答えが分かる質問だと
> 上から目線で横柄な態度で仰々しく答える。
正確には
解ってるつもりで、不適切なことを教える。
>>104 Access使うのが常道
ExcelでSQL使うのは○道
VBSやJScriptからの利用なのですが、質問させて下さい Excelを開く際にBookにパスワードが掛かっている場合 パスワード入力ダイアログが表示されますが このダイアログにフォーカスが当たっている時のIMEが全角か半角かを判定する術はありますでしょうか? 恐らく、作成したテキストフィールド等ではVBAで可能だと思うのですが (JavaScriptでも出来るので) パスワード入力ダイアログで、どう判定するのかご存知でしたら教えて下さい
win32APIのimm32.dllを使うのはどうかしら
と言うか、開くだけならopenの引数にパスワード入れればいいし、入力させるならそんなに神経質になる必要もない
125 :
デフォルトの名無しさん :2010/08/23(月) 20:05:43
>>123 DLLは環境的に使用できません
>>124 開くExcelはユニークで固定じゃない
だからパスワードは開く時に同時に処理するってのは無理で、
あくまでユーザーサイドで入力をさせたい
で、ユーザーサイドの入力支援スクリプトとしてJSファイルを作成中
Sendkeys("password123")だけだとIMEが全角の時やラージ文字だと失敗するから、これを防ぎたい
CAPS LockやShiftのキーコードで、半角ラージ文字は問題なくいけたけど
全角時は何故かダメだった…全く理由が分からないので
Excel側でパスワード入力ダイアログを制御出来る関数とかないのかなぁ、と
つ アスキーコード
エクセル開いてIME無効にしてからターゲット開くとか
128 :
デフォルトの名無しさん :2010/08/23(月) 22:42:11
>>126 コードを漁ってみます
助言ありがとう
これで無理なら諦めますわ
>>127 ターゲットのBookが直に開かれる仕様なので無理ですね
スレ違いに等しい内容に付き合ってくれて、ありがとうございました
129 :
デフォルトの名無しさん :2010/08/23(月) 22:45:37
>>126 まだ試してないですがアスキーコードならいけそうですね!
助かりました。視野が狭くて恐縮です
スレ汚しスマソ
質問です。 「かぼちゃ」 「だふぁfだd」 などと文字がランダムに並んだ文字列があります。 これを 「ゃちぼか」 「dだfぁふだ」 という風に、文字列を逆にしたいのですが 解決する方法はあるでしょうか?
下記の通り、エクセルでDLLを呼び出すと、なぜかエクセルが強制終了します。 同じような経験をされた方がいらっしゃいましたら、対処方法をご教授いただきたく。 目的:VBAで用意した構造体にdllで計算した値を格納したいです。 →これが可能であれば、intとdoubleを15個ほど織り交ぜた構造体で実装したいです。 VBA(Excel2003) --------------------------------------- Type XXX x as integer y as integer z as integer End Type Declare Sub adder Lib "c:\test.dll" Alias add(ByRef a as XXX) Sub test() Dim s as XXX s.x=1 s.y=2 s.z=0 Call adder(s) Cells(1,1)=s.z End Sub ---------------------------------------
132 :
つづき :2010/08/27(金) 02:24:02
C++(VC++2008express) --------------------------------------- typedef struct { int x; int y; int z; } XXX; extern "C" void _stdcall add(XXX * s) { int a=s->x; int b=s->y; s->z=a+b; } ------------------------------------- test.def ------------------------------------ LIBRARY test.dll EXPORTS add @1 ------------------------------------
相談させてください。 1=2=3=4= 例えばこのような文字列があるセルにあったとき、これを区切り位置機能で 1 =2 =3 =4 = のように各セルに分割したいです。 TextToColumns Destination:=Range("A1"), DataType:=xlFixedWidth, _ FieldInfo:=Array(Array(0, 1), Array(1, 1), Array(3, 1), Array(5, 1),以下略 で分割すると結果セルの中身は=2や=3は2や3になってしまいます。 最初に該当するセルの書式をすべて文字列にしてからこの処理にかけても 値の上では=2,=3になるのですが、表示の上では2や3になり、 ダブルクリックして一度編集モードにしないと=2,=3と表示されません。 分割した時点で=2,=3と表示させるにはどうしたらよいでしょうか?
つ "'"&
>>135 いや、区切った時点で=2ではなくなってしまうみたいで、
区切った直後のコードで
Cells(1,1) = "'" & Cells(1,1)
としても=は残らないんです。
区切る前にテキストの特定の文字数部分に"'"を入れれば出来るかもしれませんが手間がかかりすぎます。
>136 区切る前に置換すれば? そもそも先頭に=を持ってくる様な処理が腐ってる。
>>136 >>137 をヒントにして、
Dim a, b, c, d
a = "1=2=3=4="
b = Replace(a, "=", "@'=")
c = Split(b, "@")
For Each d In c
Debug.Print d
Next
こんなのどう?
>>138 コーディングや関数とは無関係に文字列としての=が先頭に必要な事態になったんだから
そんなこと言ってもしょうがない。
>>139 ありがとうございます!区切り位置で頭が固まっててsplitを思いつきませんでした。
助かりました。
おちつけw
お前らはvbaをどこで使ってるの?やっぱ仕事?
142 :
デフォルトの名無しさん :2010/08/28(土) 15:55:37 BE:773310454-2BP(1201)
VBを経由してexcelを開かせたいのです 普通に起動したらelcelを強制終了したいですがどうしたらよいでしょうか?
普通に起動ってなに?
144 :
デフォルトの名無しさん :2010/08/28(土) 17:08:52 BE:386655825-2BP(1201)
その他以外の目的でExcel使うときはどうするの?
日本語が変だった。 「その目的以外(つまり通常の方法で)でExcelを使うときは~」と書きたかった。 いずれにせよ、エクセルを殺すことになるんじゃない。
EXCELVBAだけならじゃムリ EXCELアイコンをEXCEL開かないようにして,クリックしたら終了メッセージだけ出すとかなら出来そうだけどVBAじゃねえな
>>142 ちょっとやりたい事(理由)が分かりずらいんだけど
特定ブックは VBA経由以外では開かせたくないって事かな?
そのブックにパスワードを設定しておくってのはどうです?
1)VBAなら パスワード指定でオープンする
2)普通にオープン(パスワードを知らないと開けない)
どう考えても仕様を練り直した方が良いレベル。
Excelを起動してからじゃないとVBAは動かせないんだから、 Excelの起動を禁止したら、そのExcelを開くためのVBAはどうやって開くんだよ
ADのグループポリシー側でやるとかしか無いんじゃないのかなあ。
フラグが経ってなければ自動で終了させればいいだけかもしらんが
どうせ、スタートメニューからExcelのショートカット消せば解決する程度の話だろ?
>>142 VBAからでなくて、VBからExcelを呼び出すのだよな?
そのVBのプログラムが起動しているかチェックして
起動していなければ終了、というVBAをブックオープン
イベントに記述しておけばいいんじゃないの。
特定のプログラムが起動していることをチェックする方法は
俺は知らないけど、この手のOSに近いことはマイクロソフトの
製品なら得意のはず。
開いた時にレジストリにフラグ書き込んでおけば?
API呼べばプロセスはチェックできる
チェックするためのExcelを開いていないとAPIも呼べないな VBSで常駐させとくか?
文字列変数に >このデータは{あいうえお,abcdefg}です というデータが格納されているとします。 これを >このデータはあいうえおです >このデータはabcdefgです というように抽出する手っ取り早い手段に悩んでいます。 {}の中にはカンマ区切りで2種類のデータがあり3種類以上になることはないという条件です。
>>158 s = "このデータは{あいうえお,abcdefg}です"
p = InStr(s, ",")
t = "このデータは" & Mid(s, 8, p - 8) & "です"
u = "このデータは" & Mid(s, p + 1, Len(s) - p - 3) & "です"
Debug.Print t
Debug.Print u
では後出しの条件をどうぞ↓
161 :
158 :2010/08/29(日) 22:42:32
言い忘れましたがデータ中に区切りではないカンマも含まれる場合があります。
なりすましは無視して s = "このデータは{あいうえお,abcdefg}です" a1 = Split(s, "{") a2 = Split(a1(1), ",") a3 = Split(a2(1), "}") t = a1(0) & a2(0) & a3(1) u = a1(0) & a3(0) & a3(1) Debug.Print t Debug.Print u
なんかモヤモヤする
>163 俺もそう思う。 でもここでメモリの無駄遣いを説いても分かってくれないだろうし・・・
165 :
デフォルトの名無しさん :2010/08/30(月) 15:50:25
面白そうなことやってるな、俺も混ぜてくれ s = "このデータは{あいうえお,abcdefg}です" Set re = CreateObject("VBScript.RegExp") With re .Pattern = "(^.+{)([^}]+)(}.+$)" .IgnoreCase = True .Global = True args = Split(.Replace(s, "$2"), ",") For Each arg In args Debug.Print (.Replace(s, "$1" + arg + "$3")) Next End With メモリ効率?んなもん知らんわw
s = "このデータは{あいうえお,abcdefg}です" w = Replace(Replace(s, "}", ","), "{", ",") a = Split(w, ",") t = a(0) & a(1) & a(3) u = a(0) & a(2) & a(3) Debug.Print t Debug.Print u
a = Split(Replace(Replace(s, "{", ","), "}", ","), ",")
ユーザー定義書式
面白れぇ~w
このデータは{あいうえお,abcdefg}です 文字列変数にこんな風に格納されないようにしたほうが早いんじゃないか?
171 :
われは海の子 :2010/09/02(木) 11:07:40
はじめまして 2ちゃん初心者です VBA画面でオブジェクト(Sheet1(表紙)~・・・)が たてに並んでます。23こ。 あれがオブジェクト名順に並んでないんですがどうしてですか? シート名順に並んでいるわけでもありません。 オブジェクト名順に並び替えるにはどうしたらいいですか?
1,10,2,3…という並び方なら心当たりがある。そういうケースだとしたら、 01,02,03…と命名すれば吉
173 :
われは海の子 :2010/09/02(木) 11:32:56
まさに! Sheet01(表示)にしなければだめですか? for文で回したりするときなどに 支障がないか心配です。。。
174 :
われは海の子 :2010/09/02(木) 11:44:16
試しましたが無事できました! for文で回すのにも 支障はなさそうですね! ありがとうございます てかこんな単純なことになんで気付かなかったんだろか。。。
シート名って作った順番に内部的な番号が振って無かったっけ? そういう話じゃなくて?
内部的にはオブジェクト名。 表に見えるシート名は、シートのNameオブジェクト。 オブジェクト名は自動的に連番で命名されてしまう。 そのままでは不便な場合もあるので、 オブジェクト名はりネーム可能。
158です。
アドバイスありがとうございます。
>>170 どうしてもこの様式にしなければならないのです><
>>166-167 の方法でいきたいと思います。
178 :
デフォルトの名無しさん :2010/09/05(日) 15:44:41
エクセルのVBAでHTMLファイルのHTMLタグを除去したいと思っています。 ファイルの入出力はできるのですが、タグ除去の部分をスマートに書けません。 スマートにコードを例を挙げて教えていただきたくよろしくお願いいたします。
読み込む 一致したタグを書き換えもしくは排除する タグ内のテキストを書き換える 書き出す たまにタグ閉じてない場合困りそうだが
180 :
デフォルトの名無しさん :2010/09/05(日) 18:25:42
>>179 ご回答ありがとうございます。
やはり一行ずつ変換していくしかないのでしょうか?
こんなシロウト丸出しでやっているんですが、これじゃあなあって思っています。
buf = Replace(buf, """", "")
buf = Replace(buf, "<META NAME=robots CONTENT=noindex,nofollow>", "")
buf = Replace(buf, "<HEAD>", "")
buf = Replace(buf, "</HEAD>", "")
buf = Replace(buf, "<pre>", "")
buf = Replace(buf, "</pre>", "")
完璧だ res = "" flg = false for i =1 to len(buf) if mid(buf, i, 1) = "<" then flg = true elseif mid(buf, i, 1) = ">" then flg = false elseif flg = false then res = res & mid(buf, i, 1) end if next
>>180 タグが2行にまたがった場合とか、属性値とかコメントとかスクリプトが埋め込まれた場合とか考え始めると意外に難しい
実際にブラウザで表示してしまって、テキストをコピペするのが実は一番簡単だったりする
無難なところでは正規表現を使う。"<"で始まって">"で終わる文字列をまとめて痴漢とかできるから
まあ、正規表現が無難だよな。
184 :
デフォルトの名無しさん :2010/09/05(日) 22:39:18
>>181 HTMLを知らないのでとりあえず目に付くものだけを変換していました。
タグを認識するんですね。試してみたいと思います。ありがとうございました。
>>182 >>183 コピペが面倒で複数のHTMLファイルからテキストファイルを作りたいと思っています。
正規表現について調べてみたいと思います。ありがとうございました。
>>184 そのコピペの作業をVBAで自動的にやらせるんだよ
元のHTMLの状態にもよるけど、ブラウザにデータ変換やらせた方が間違いがないし簡単
とくにJavaScriptとかで動的に生成してるページだとソース解析は不可能に近い
>>178 dom使えばいいんじゃないの?
Sub test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Navigate "
http://www.yahoo.co.jp/ "
.Visible = True
Do While .busy And .readystate <> 4: DoEvents: Loop
Range("A1").Value = IE.document.body.innerText
.Quit
End With
End Sub
>>186 その方法ってローカルに置いたファイルでも使える?
>>187 使えない理由が思いつかないけど。試してから言ってる?
ローカルファイルのセキュリティ制限は普通に行われるから
途中で止まってるように見えるのかもしれないが、
放っときゃタイムアウトで処理は正常に終わる。時間かかるけど。
それが嫌ならDoLoop文で.busy見るのやめて、
.ReadyStateがInteractive(3)以上ですぐテキスト読めばいいんじゃない?
グリグリ動的生成するようなHTMLじゃないんだろうし、それでいいと思う。
(質問主は直接読んでたくらいだし動的内容は考慮する必要ないっしょ)
Do While .readystate < 2: DoEvents: Loop
セル自体にValueプロパティ以外の方法で値を持たせておく方法を探してます ユーザーが簡単にいじれない(いじる意味が無い)プロパティとかないですかね? IDプロパティは見つけたんですが、これ以外に複数あればなお良しって感じです
書式設定をリストにしてフラグにするとか 表示形式を暗号化するとか。 いじれないってことになると,あとはパスワードでロックかけるとか。 ロックセル内に書き込むとか,パスワード自体を文字列にするとか。
>>188 187じゃないけど、ちょっと試した限りではXPではOKで、Vistaだとダメっぽい
ローカルファイルへのnavigateは成功するけど、
navigateした後、IEへのインスタンス自体が無効化されてるみたいに見えるので
単純に遅いという話ではないよう
>>189 数値や文字コードを文字の色、セルの色(RGB値)、幅、高さ、罫線の組み合わせなどに置き換えるとか
そんな面倒なことするよりデータそのものを独自ルールで暗号化した方が捗ると思うけど
vbaのソースの差分を表示してくれるツールない?
IEの制御ってなんか一癖あった気がする
196 :
189 :2010/09/07(火) 09:46:43
>>190 >>193 IDに独自ルールで複数捻じ込むのが一番楽そうですねぇ
ありがとうございました
>>194 統合環境の上で差分を表示してくれるツールは見たことない
エクスポートすると単なるテキストファイルになるから、テキストを比較するツールならなんでも使える
>>192 こりゃ分かりやすいな
以前のバージョンでも、CreateObjectでIEアプリケーション呼び出すときに、
ブランクをNavigateしないと処理出来ない仕様だった気がする
199 :
デフォルトの名無しさん :2010/09/12(日) 00:58:12
JSON形式のデータをパースする方法ってないですかね? Script Control使ってevalで評価するやり方は、JSONデータに配列が含まれてるとダメみたいで。。。 教えてエロイ人!
200 :
デフォルトの名無しさん :2010/09/12(日) 14:50:41 BE:1082634847-2BP(1201)
excelを起動したと同時に処理を始めたい どんなプログラムを記述すればいいですか
エクセルシートの中から別のエクセルアプリケーソンを軌道するって 違反ですか?
202 :
デフォルトの名無しさん :2010/09/12(日) 16:13:19 BE:1391959049-2BP(1201)
>>200 エクセルをオープンしたら自動で読み込むモジュールがあるから,これを使う
204 :
デフォルトの名無しさん :2010/09/12(日) 19:38:07 BE:2165268487-2BP(1201)
205 :
デフォルトの名無しさん :2010/09/12(日) 19:41:43 BE:1739948459-2BP(1201)
あるセルに入力されてるセルのアドレスに別のデータを貼り付けたいんだけど、 これって無理難題ですか?
アウトラインのグループ化で列をグループ化したあと それを非表示にするにはどうしたらいいですか?
Excel2007 fileを移動する事について聞きます FSO.MoveFile の場合,同名のファイルが移動先に有るとエラーになるとありますが 上書きで移動するというのは出来ませんか? FSO.CopyFile の場合コピーした後消す処理が必要になります 上書きで移動出来たらその消す処理も要らないのですが。
>>208 一発で上書き移動する方法はないのでもう一行追加して自分で消して下さい
211 :
デフォルトの名無しさん :2010/09/13(月) 18:27:33
>206 INDIRECT関数を使う
わからないので教えてください dim k_0 as single, ab(4) as single, cc(4) as single k_0=0 for i=1 to 4 k_0=k_0+ab(i)*cc(i) next で4行目に 型が違います のエラーが出てきます。助けてください
配列にどんな値が格納されてるか書いてないから何とも言えないなぁ。 Option Baseで1を設定して無ければ、配列は0のインデックスから始まるけど、そこは大丈夫?
配列の値はどれも小数点以下8桁くらいの実数値です option base見逃してました. ありがとうございます
option base 1 dim k_0 as double, ab(4) as double, cc(4) as double k_0=0 for i=1 to 4 k_0=k_0+ab(i)*cc(i) next でも型が違いますのエラーがでました....orz
>>215 変数iの型が何か怪しげなものになっている予感。
明示的にLong型で宣言してからだとどうなる?
dim i as long でやってみましたがダメでした msgbox typename(i) はinteger でした
<<217 追記 同じように型が違います のエラーです
k_0=k_0+ab(0)*cc(0) k_0=k_0+ab(1)*cc(1) k_0=k_0+ab(2)*cc(2) k_0=k_0+ab(3)*cc(3) て並べて演算するデバッグを試してみれ。 とりあえず、小数点8ケタの実数を配列2個に代入してから同じ式で演算したけどエラー出ない。
うーん、型が違うエラーが出るのは分からんなぁ。 k_0=k_0+cdbl(ab(i))*cdblcc(i)
途中送信しちゃった・・。 k_0=k_0+cdbl(ab(i))*cdbl(cc(i)) 配列にStrとか入って無いかな? 型変換で無理やりdoubleにしてから計算してもエラー出るかね。 for i=1 to 4 k_0=k_0+ab(i) next みたく、配列1個ずつやって試すのだ。 1個ずつやってエラーが出なかったら、 msgbox ab(1)*cc(1) で型エラーが出るか試す。 まずはforで回す前に、どこでエラー吐いてるのかを調べるべし。
>220 >222 やってみます
k_0 = k_0 + ab(1) * cc(1) k_0 = k_0 + ab(2) * cc(2) k_0 = k_0 + ab(3) * cc(3) k_0 = k_0 + ab(4) * cc(4) For i = 1 To 4 k_0 = k_0 + ab(i) * cc(i) Next これでやったらfor next の中だけエラーになりました どうやらi のせいらしいです
OK、次のステップだ。 i = 1 k_0 = k_0 + ab(i) * cc(i) i = 2 k_0 = k_0 + ab(i) * cc(i) i = 3 k_0 = k_0 + ab(i) * cc(i) i = 4 k_0 = k_0 + ab(i) * cc(i) これでエラー出るかね?
キタ - .∵・(゚∀゚)・∵. - ッ!! ほかのとこでエラーだけど
いや、詳しく書いてくれないと。
>>225 ではエラー出なくて、forで回すとエラーが出るって事かい?
>>225 はあくまでデバッグだから、最終的にはループさせないと話にならんし。
>>218 longで定義してるのにinteger吐いてるのはやばくね?
>228 longを外すとinteger でした >227 for nextに戻しても動きました なんでだろう
とりあえず解決? カウンタ変数はlongで明示的に定義する癖付けると良いよ。
解決しました あと÷0を強制的に行う関数ってありますか?
0で除算すると必ずエラーが出る。 ”0で除算しました”ってerr.description。 0で割っちゃ駄目なんだよ。 1/0 = 0 と仮定すると、 2/0 = 0 つまり、 1 = 2 と成り立ってしまうから、0では除算出来ない。
いろいろありがとございました これでなんとか組めそうです
どなたか宿題を手伝ってください… [前提] セルA1には、以下のような文字列が入っています。 --------------------------------------------------------- ガム ??????-??? キャンディ ??????-??? クッキー ??????-??? チョコレート [??????-???] ポテトチップス【??????-???】 --------------------------------------------------------- [問題] セルA1の??????-???部分のみを抜き出し、 セルA2に以下の形式で出力して下さい。 --------------------------------------------------------- ??????-???, ??????-???, ??????-???, ??????-???,??????-??? --------------------------------------------------------- というような問題を出されたのですがサッパリ分かりません…
>>234 文字化けしてるのか、そういう問題なのか
そういう問題だとしたら問題を作った方が問題だ
>>234 ?って、任意の半角英数字文字なのかな?
データの左から右へマイナス記号を検索して
見つかった位置から左6文字・右3文字の
領域を取り出して一つの文字変数に連結する。
それをデータの終わりまで繰り返す…かな。
?の数が商品によって違うのなら俺にはお手上げ。
わかったこれぜんぶA1に入ってるんだろガムもチョコも で、任意の数字5-3文字を抜き出してA2にまとめるんだ 空白+かっこで判定するか数字で判定するか ループして一文字ずつ抜き出し 数字か-ならA2転写 連続が途切れたら, こうじゃね 多分ループとlenとmidを使わせる宿題
>>234 A1内を??????-???で検索して??????-???がヒットするから
ヒットした数だけ??????-???をA2に繋げて入れりゃいい
裏技として
??????-???が固定なら最初からA1無視して決め打ち??????-???をA2に入れりゃ宿題完成だ
>>235 ,
>>236 説明がヘタですみませんm(__)m
?部分は任意で??????-???(数字6文字-数字3文字)の形式で、全て同一のセルに書かれていました…
>>237 おっしゃるとおりで、??????-???(数字6文字-数字3文字)で判定させたいようです
難しすぎる…(´・ω・`)
>>238 ほんとに説明がヘタですみません…
文字列は固定ではありませんでした
とりあえず1限に行って参ります…(´・ω・`)
セル内改行で複数のデータが詰め込まれてるところから 英数字の部分を抜き出してコンマ区切りで並べろってこと? つまり、全角文字とスペースと記号、半角英数とハイフン、が区別できればいいの?
純粋に6-3一致のみ抜き出せばいいと思われ
問題の前提条件が今ひとつよくわからないんだが、 数字の桁数が固定でハイフンが1行に1つという前提で さらに使っていい関数などが無制限なら比較的簡単にできる Sub 変な課題() a = Split(Range("A1"), Chr(10)) For i = LBound(a) To UBound(a) a(i) = Mid(a(i), InStr(a(i), "-") - 6, 10) Next Range("A2") = Join(a, ",") End Sub
>>243 あんたすげーわ。
セル内改行で区切られているデータならこれでバッチリだ。
SplitやJoinなんて命令がVBAにあるなんて知らなかったぞ。
質問主がこれで幸せになれることを祈ろう。
テキストファイルからExcelにコピペしたデータを
編集・整形したいときに使える技だな。
俺も参考にするよ。
245 :
デフォルトの名無しさん :2010/09/14(火) 19:22:22
個人的には正規表現でサクっと組みたい所だな。 まぁ、宿題だから×もらうだろうけど。
247 :
デフォルトの名無しさん :2010/09/14(火) 20:31:05
>>246 正規表現の宿題かもしれないぜ?
質問者レベルからしてそれはないだろうけど
正規表現だと、こんな感じのをFor文で繰り返すのかな
カンマはA2がNullの時は分岐する必要があるか
re.Pattern = "\d{3}-\d{6}"
re.Global = True
re.IgnoreCase = True
Set Matches = re.Execute(tmp(A1))
If re.Test(tmp(A1))=true Then
Range("A2").Value = Range("A2").Value &","& tmp
End If
学校でVBA教えるとしても、VBSの正規表現まで教えるかな? どうせ学校で教えるならperlとかjavaの正規表現を教えるような気もするが。
学校の課題だとLenで文字数調べてWhileで半角数字が出て来るまで回すとか、 もっと原始的な方法を教えるような希ガス 少なくとも宿題丸投げレベルの子がいきなりSplitとUbound使ってきたら 絶対に自力でやってないとバレるだろ どういうロジックか説明しろと先生に問い詰められて自爆するのが目に見えてる
>>243 こんばんは、質問した主でございます…
示していただいたコードで欲しかった結果が正に出ました…
感謝でもう言葉が…(´;ω;`)本当にありがとうございます
理屈を少し考えてみたのですが、
1.A1に格納されているデータを改行で分離する。
2.分離した最初の行から、最後の行まで繰り返す。
3.-を含む10文字を抽出する。
4.抽出したデータをA2に,区切りで出力する。
>>246 ,
>>247 ,
>>248 ,
>>249 正規表現という言葉は聞いたことがありますが、何のことがさっぱりです…
問い詰められちゃったら…(´;ω・`)
>>236 のアルゴリズムで作ってみたぞ。
こっちは改行があってもなくても動くはず。
Sub 変な宿題2()
Dim MAE, ATO As String
Dim i As Long
MAE = Range("A1").Value
ATO = ""
For i = 1 To Len(MAE)
If Mid(MAE, i, 1) = "-" Then
ATO = ATO & Mid(MAE, i - 6, 10) & ","
End If
Next i
Range("A2").Value = Left(ATO, Len(ATO) - 1)
End Sub
>>251 ループで連結して最後に余分なコンマを消すなら
ATO = ATO & "," & Mid(略)
……
Range("A2") = Mid(ATO, 2)
の方がちょっとだけスッキリ
半角全角混じった文字列の何バイト目から何バイト目を切りだす、という処理をする時、MidBのバイト数カウントと文字コードの都合から StrConv(MidB(StrConv(文字列, vbFromUnicode), n, r), vbUnicode)) と書かないとダメでしょうか? 何かすごくスマートさに欠ける気がひしひしとするのですが、 もっとちゃんとした書き方はありますか?
仕様がスマートじゃないから仕方がないと思う。
入門書って色々あるけどどれがいいかな
>>253 何度も切り出す処理をする時は、
全角文字の後ろにヌル文字(vbNull)を挿入して1バイト=1文字の形にした上で、
切り出した後にReplaceでヌル文字には消えてもらう、
というようなやり方を俺は使っているな。
始めの挿入処理が多少面倒だけど、一度作れば使い回しが効くし。
257 :
デフォルトの名無しさん :2010/09/16(木) 17:10:46
258 :
デフォルトの名無しさん :2010/09/16(木) 18:36:26
あのマリオは見た限りゲームプログラムとしては……
昔テトリスやったな ボスが来た!てやつ
261 :
デフォルトの名無しさん :2010/09/17(金) 11:38:44
worksheet型(object型)の変数をモジュールレベルにすることはできないのでしょうか? 定数にできたら一番良いのですが、どうすればよいでしょうか? 今のコードは Dim W1 As Worksheet Dim W2 As Worksheet Sub pc1() Set W1 = ThisWorkbook.Worksheets(1) Set W2 = Workbooks("hogehoge.xlsm").Worksheets(1) ~処理~ End Sub Sub pc2() W1.Cells(処理~ W2.Cells(処理~ End Sub こんな感じになっていますが、pc2()でW1を使おうとすると エラー1004:アプリケーション定義またはオブジェクト定義のエラーです。 が出てしまいます
262 :
デフォルトの名無しさん :2010/09/17(金) 11:44:20
>>261 補足:pc1()の中でpc2()をcallしています
よろしくお願いします
>>261 Dim W1 As Worksheet
Sub pc1()
Set W1 = ThisWorkbook.Worksheets(1)
Call pc2
End Sub
Sub pc2()
W1.Cells(1, 1) = "○"
End Sub
これで正常に動いてる
エラーの原因はお前のやってる処理の部分に問題があると思われ
264 :
デフォルトの名無しさん :2010/09/17(金) 13:30:26
>>263 そ、そうなんですか!ありがとうございます!
ちなみにConstで定数にすることってできませんよね?
Set使わなきゃならないからどうすればいいのかわからない
"A"→1 "B"→2 "Z"→26 "AA"→27 "AB"→28 文字列から列番号へ一発変換する関数はありますか?
266 :
デフォルトの名無しさん :2010/09/17(金) 19:02:15
一発じゃないけどINDIRECTとCOLを組み合わせたらどうだろう?
>>265 そんな処理が必要あるわけないと思うがColumns("AB").Column
まさか下のようなまわりくどいことやるなよ。
y=Columns("AB").Column
Columns(y).****
>>264 そんなもの引数で渡せよ。
Sub pc1()
Dim W1 As Worksheet
Set W1 = ThisWorkbook.Worksheets(1)
Call pc2(W1)
End Sub
Private Sub pc2(W1 As Worksheet)
W1.Cells(1, 1) = "○"
End Sub
名前をW1でそろえる必要はないけどな。
あとどうせ渡すならより下位のRangeを渡したほうがいいと思うが。
質問です。 選択範囲内の文字列を検索して置換するものなのですが、 ・入力されてる文字列は不定 ・その中で「aaaあああbbbb」って文字列の「aaaa」があれば「bbbb」を「cccc」にする っていうのがうまくできません。 何かいい方法は無いでしょうか? 選択範囲内をFor文で回すと時間かかるのがネックで・・・。 例) 1234bbbb aaaa1234bbbb ↓置換 1234bbbb aaaa1234cccc
271 :
デフォルトの名無しさん :2010/09/18(土) 16:42:05
どう上手くできていないのか、その出来ていない部分を晒しなさいって
272 :
デフォルトの名無しさん :2010/09/18(土) 18:29:40
>>271 うまくできません=わかりません
なのだろう。察してやれよ。
>>270 文字列の前提がもっと欲しい。
aaaa、bbbb=半角アルファベット
あああ=半角数字
なのかな?
それとも
aaaa,、ああああ、bbbbの各文字数が
半角4文字ずつなのかな?
お前らはやっぱり会社でvba使ってるの?
276 :
デフォルトの名無しさん :2010/09/18(土) 23:00:12
社内SEやってたときは VBAでの開発もよくやってたよ
>>275 そうだよ。
不況だから、ちょっとデータを加工したいくらいの
用途では、開発予算が取れないもの。
景気の良いときには、外部の開発業者が部門に常駐していて
頼めば何でもやってくれたんだけどね。
VBAだとExcelの付属物という位置づけなので
社内の監査(勝手にプログラムを入れるなとか)なんかも厳しくない。
パスワードをかけられるのでセキュリティ上も安心できる。
お金のない社内部門システムには、VBAは救世主。
スレ違いかもしれんが…
>>276 ,277 失礼だけど中小企業?
>>277 の言うことはよくわかる
ウチもまさにそんな感じ。ウチは製造の中小。
279 :
276 :2010/09/18(土) 23:43:35
エクセルの2つのワークシートを比較して、異なるセルを書き出すという単純な処理をしたいのですが、for next 文を行列二回回すしかないですか? for eachで出来るのですか? あと処理班速度はいかがですか?
>>280 for next文を2回回すしかない
速度はそれほど早くない
速度に関しては、直接をセルを参照するのではなく、いったん変数(2次元配列)に格納して処理
すれば格段に早くなるはず
>>280 For Eachは1つのコレクション内の各要素を暗黙的に
処理するので添え字がなく、2つのシートのセルを同期を取って
処理することには使えないと思う。
以下のようにしてセル範囲に添え字を付けると
一次元配列っぽくアクセスできるので、Forは一つで済むうえに
添え字で別シートの同一位置のセルにもアクセスできるはず。
Sub 範囲添え字アクセス()
Dim 範囲 As Range
Set 範囲 = Range("A1:E10")
For i = 1 To 範囲.Count
Debug.Print 範囲(i).Value
Next
End Sub
しかし、
>>281 の言う通りセルへのアクセスを繰り返すと
セル数によってはかなり遅いので、二次元配列に取り込んで
二重ループで回すのが良いかも知れない。
二次元配列への取り込みは以下のようにすれば簡単にできる。
Dim V As Variant
V = 範囲.Value
勉強になりました。 ありがとうございます。
値が違うところをピックアップしたいのかな? 関数でも解決できるけどvbaがいいんかね
非常に単純な質問で申し訳ないのですが、なぜか調べても分からなかったので教えてください。 変数に+1をする式ってどうやって記述すればいいのでしょうか。 a=a+1 ではなく、 a++ とか、そういうふうに記述すると+1できるやり方があったと思うのですが、どうにも思い出せません。 ご存じの方教えてください。
>>285 VBAにはそういう命令はない。
a =a +1のみ。
まず何から勉強したらいいのか分からない 初心者が勉強できるサイトとか教えてください
>>280 for each Rng in sheets(1).range(cells(1,1),cells(10,10)
with sheets(2)
if rng.value <> .cells(rng.row,rng.column).value then
msgbox "aaa"
end if
end with
next
>>287 moug
office tanaka
Excelでお仕事
>>287 素直に本屋に行って何冊か入門書を買え
サイトで手軽にすまそうとするな
mougとかOfficeTANAKAとかぐぐればいっぱいあるはずだけど、そう言うのも見つけられない状態なんだろ?
291 :
287 :2010/09/19(日) 18:11:36
みなの衆 ご苦労 大儀であった
Excel2003の質問です。 複数のシートを選択している時、選択されているシートの一覧を取得したいと思っています。 Worksheetのメンバを見てみたのですが、Selectedのようなものは見つけられませんでした。 どのように取得したらよいでしょうか。 よろしくお願いします。
>>292 For Each Sh In ActiveWindow.SelectedSheets
Debug.Print Sh.Name
Next
とかかな
>>280 に関して横から質問
比較する範囲の指定方法ってどうするのがベストかな?
とりあえず思いついたの
Dim R, C
Dim Range1, Range2
R = WorksheetFunction.Max(Sheets(1).Cells(1, 1).SpecialCells(xlLastCell).Row, _
Sheets(2).Cells(1, 1).SpecialCells(xlLastCell).Row)
C = WorksheetFunction.Max(Sheets(1).Cells(1, 1).SpecialCells(xlLastCell).Column, _
Sheets(2).Cells(1, 1).SpecialCells(xlLastCell).Column)
Range1 = Range(Sheets(1).Cells(1, 1), Sheets(1).Cells(R, C))
Range2 = Range(Sheets(2).Cells(1, 1), Sheets(2).Cells(R, C))
>>293 Windowオブジェクトは考え付きませんでした。
無事取得できました。有難うございました。
>>294 range型ってsetしなくても良いの?
297 :
294 :2010/09/20(月) 23:57:01
>>296 説明不足でゴメン
variant型に2次元配列の形で代入したつもりだった
質問です。 Excel2003ですが、選択したセルの上下左右の罫線を調べるには、どうしたらいいでしょうか? ヒントなり考え方でもいいです。 因みに、罫線の設定なりはできます。
MsgBox Cells(1, 1).Borders(xlEdgeBottom).LineStyle
298です。 素早い解答ありがとうございます。 これで目処がたちました。 ウィザードリィが作れそうです。
>>300 ウィザードリィなのかwwww
なんか面白そうだな
なんか、ふと思い付いたんです。 Excelで出来るじゃないかと。 イベントや戦闘は、基本乱数計算だし、3Dはセル結合と罫線で描写出来るし まぁ、問題はマップの移動を、どう3Dに反映させるかだったんですよ
>>302 おお、セルで描画するのか。時間掛かってもそれの方が味があるな。
ただ画像をキャプチャしておいて表示させた方が、マップとの同期は簡単だよね。
あ~なるほど、確かにその方法だと色のついた壁なんかも出来ますね。 でも、各セル毎ごとに数値なり入れておいて判別させるのです?
マップ用のシートを用意しておいて、自分がどこにいるかを記録していくのが王道かな。 昔は2次元や3次元配列に情報を記録しておいたんだけど、スプレッドシートがあるExcelならば、 シートに記録して行った方が処理は可視的だし圧倒的に楽だと思う。 もし俺が今作るなら、セルをマップに見立てて、セルに扉の情報を文字で持たせるかな。 北扉:1、東扉:2、南扉:3、西扉:4 みたく。 北と南に扉があるなら13 みたいに。 んで、Instrでセルの文字列を解析しつつ、合致した画像を表示させると思う。
307 :
☆298 :2010/09/22(水) 19:52:21
なるほど、それにプラスして 階段:D 強制戦闘:E のように組み合わせるのですね。 でも、左右に向きを変えたときの処理が困難になりそうですね。 私が考えたのは、仮にA3にカーソルがあるとして、A1方向に向いてるとします。 A3セルの上辺左辺右辺の罫線の有無、種類を判別する。 同じようにA2,A1と調べていって、実線は壁、二重線は扉てなカンジで 右に向いたときは、A2をB3、A1をC3、にして上辺右辺下辺にしてみる。 こんなかんじです
>>307 まぁ、騙されたと思ってセルに文字情報を記録しておきなって。
どっち向いてるかの情報なんて4方向の1変数で確保出来るんだし。
後々絶対に保守しやすいし、拡張もしやすいから。
309 :
☆298 :2010/09/22(水) 22:59:55
・・・(頭の中でシュミレート中)
うぉぉぉぉぉぉぉ!
理解できました!
こっちのほうが、構文短くなる!
有難うございました!
>>306 うちには3歳の悪魔がいるので、いつうpできるかわかりません><
気長に待ってください><
実際の年齢は10万3歳か
excel2003で数字カウンターを作っています。 データー→フォームで数字を打ち込んで何番が何個と言う統計カウンターです。 フォームの入力を一旦止めて後ほどフォームを開くと入力のセルに先頭の 入力済みの部分が表示されます。新規ボタンを押せば最終入力した次のセルに飛んで うまく続きを入力できるのですが、この部分をマクロで新規(w)を押した様にフォームを開きたいのですが、 登録できません。 素人ですのでうまく表現できません。すみません。 注文番号と言う表題の下 マクロで(ActiveSheet.ShowDataForm) フォームが開きます。 入力して一度保存し、改めて入力を再開するとき フォームの新規(w)を押して新しいデーターを追加していますが マクロで’追加入力’と言うボタンを作りフォーム(w)を押したのと 同じように直ぐに新規入力が出来るようにフォームを開きたいと思いますが マクロに登録されません。 1ボタンでフォームの最終データーの次に飛ばせる方法はありますでしょうか。 説明がうまくできてませんがご理解いただけた方でわかる方がいらっしゃいましたら 宜しくお願いいたします。
cells(65536,1).end(xlup).offset(1)
>312さん これはマクロの式でしょうか何処に入れればいいでしょうか? ちなみに入力のマクロ式です。 Sub 入力() ' ' 入力 Macro ' マクロ記録日 : 2010/9/23 ユーザー名 : NOTE ' ' ActiveSheet.ShowDataForm End Sub これで作成したマクロボタンを押すとフォームが表示され 注文番号が入力できますが、一旦フォームを閉じて 改めて入力を開始すると一番最初に入力した数値が表示されます。 このときフォームの新規ボタンを押せば新しいフィールドから続きとして入力出来ますが、 このフォームの新規ボタンをマクロに登録して、追加入力ボタンを作って すんなりと新しいフィールドから入力を開始したいのです。 ご教示いただいた式は何処に挿入すればいいのでしょうか? まことにすみませんが宜しくお願いいたします。
フォームを一旦閉じて、もう一度開くと、前に入力したデータが残ってるのが困ってるの? Private Sub UserForm_Initialize() UserForm1.TextBox1.Value = "" End Sub で初期化すればその問題は解決すると思うけど、多分それだけじゃないよね。 入力して行く方法が見えないんで具体的に示せないけど、こんなイメージ? Private Sub CommandButton1_Click() Dim Rng As Range Set Rng = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Offset(1) Rng.Value = UserForm1.TextBox1.Value Rng.Offset(0, 1).Value = UserForm1.TextBox2.Value UserForm1.TextBox1.Value = "" UserForm1.TextBox2.Value = "" End Sub
315 :
デフォルトの名無しさん :2010/09/24(金) 11:13:18
現在選択中のセルが任意のセル範囲(F5~F15)であるかどうか判定して 真なら別シートの商品リストに追加登録 偽ならエラーメッセージを返して登録しないというマクロを作っているのですが 下記のように全然スマートじゃないうえに範囲が広くなったらそれだけElsIfを追加しなければならず実用性に欠けています どうすればいいでしょうか?※下記のmsgboxの部分に別シートのリストへ登録するマクロが入る予定です。 Sub selcell() Dim SC SC = Selection.Address Range("A1").Value = SC 'SCの内容を可視化するだけ完成後削除 If SC = "$F$5" Then MsgBox "f5" ElseIf SC = "$F$6" Then F7~F14省略 ElseIf SC = "$F$15" Then MsgBox "f15" Else MsgBox "間違ったセルを選択しています" End If End Sub
316 :
315 :2010/09/24(金) 11:16:06
仮に組んでみたのですがこのままでは偽の場合にエラーメッセージを返す事ができません。 Sub selcelloop() Dim SC Dim i As Integer SC = Selection.Address 'SCの内容を可視化するだけ完成後削除 Range("A1").Value = SC For i = 5 To 15 If SC = "$F$" & i Then MsgBox "f" & i Else End If Next i End Sub
もっとシンプルに考えれば良いと思うよ Sub test1() Dim SelRow As Long Dim SelClm As Long Const MinRow As Long = 5 Const MaxRow As Long = 15 Const MinClm As Long = 5 Const MaxClm As Long = 6 SelRow = Selection.Row SelClm = Selection.Column If SelRow < MinRow Or SelRow > MaxRow Then MsgBox "エラー" ElseIf SelClm < MinClm Or SelClm > MaxClm Then MsgBox "エラー" Else MsgBox "処理" End If End Sub
318 :
315 :2010/09/24(金) 11:52:45
ありがとうございます! エラーから判定して偽の場合処理を行なうって所で目から鱗が落ちました 実際に動かして見たところ 選択しているセルがE列でも作動するようですが この場合 Const MinClm As Long = 5 を Const MinClm As Long = 6 としましたが大丈夫ですかね? とにかくこれで先に進めますありがとうございました
まぁ、falseから進めるかtrueから進めるかは組む人次第だと思うけどね。どっちでも良いと思うよ。 俺の場合は、処理に重要性を求める癖が付いてるだけだし。 constの4つで範囲を指定出来るように作ってあるから、 F列だけを範囲条件にしたかったらMinとMaxを同じ値(6)にすればOK。 こう作っておけば、後で範囲を変える時に、Constいじるだけだから保守しやすいでしょ。
320 :
315 :2010/09/24(金) 12:09:50
>>319 重ねてありがとうございます
実は範囲の異なるリストがいくつかあって指定が簡単なのも助かりました!
>>314 さん
>フォームを一旦閉じて、もう一度開くと、前に入力したデータが残ってるのが困ってるの?
と言うかその逆で一旦閉じた後最後のデーターに続けて追加していきたいのです。
フォームで新規(W)を押せば済むことなのですが、その新規(W)を押したときのように
フォームを立ち上げたいのです。
その式をマクロボタン登録しておけば直ぐに新しいデーターを追加できると思いまして。
>>321 どんな風にフォームからデータ追加して行ってるのかな。
最終行の1行下ってのは、 cells(65536,1).end(xlup).row で取得出来るよね。
>>314 で提示したコードは、入力ボタンを押すとデータ最終行の1行下にデータを記録するコードね。
差支え無ければ、入力(新規?)のボタンに登録してあるマクロを見せて欲しい。
どの様に入力して行ってるかによってコードがかなり変わってくるし、
ちょっとイメージがつかめないんだ。
323 :
デフォルトの名無しさん :2010/09/24(金) 13:36:13
=VLOOKUP(DL16,DF16:DJ75,5,"--") DL16の値をDF16:DF75の中で見つけてその行の5列目を表示させたいのですがこれじゃあうまくいきません。どうすればいいでしょうか。
ここは Excel VBA 質問スレ Part16
>>323 =VLOOKUP(DL16,DF16:DJ75,5,FALSE)
↑
だと思う
326 :
デフォルトの名無しさん :2010/09/24(金) 14:10:27
>>322 さんへ
321・314です。
当方ど素人のためにご足労掛けます。
マクロは以下のようなものです。入力項目は2項目で注文を受けた
番号を入力しています。
当然新規入力なので入力されたものを一旦クリヤーしています。
--------------------------
Sub 新規入力()
ActiveWindow.FreezePanes = False
Range("B3:B3000").Select
Selection.ClearContents
Range("P4002:P4003").Select
Selection.ClearContents
Range("P4005:Q4006").Select
Selection.ClearContents
Range("B2").Select
ActiveSheet.ShowDataForm
End Sub
----------------------------
これとは別で追加入力というマクロボタンを作って
すみません、書掛けで登校してしまいました。
>>322 さんへ 321・314です。
当方ど素人のためにご足労掛けます。
マクロは以下のようなものです。入力項目は2項目で注文を受けた番号を入力しています。
当然新規入力なので入力されたものを一旦クリヤーしています。
--------------------------
Sub 新規入力()
ActiveWindow.FreezePanes = False
Range("B3:B3000").Select
Selection.ClearContents
Range("P4002:P4003").Select
Selection.ClearContents
Range("P4005:Q4006").Select
Selection.ClearContents
Range("B2").Select
ActiveSheet.ShowDataForm
End Sub
----------------------------
これとは別で追加入力というマクロボタンを作って
----------------
Sub 追加入力()
Range("B2").Select
ActiveSheet.ShowDataForm
End Sub
---------------------------
と言うマクロで追加の入力をしています。
このデーターフォームの新規(W)を押して追加の番号を入力していますが
この新規(W)のボタン操作をしないで直ぐに新規(W)を押したときのようにマクロを書けないでしょうか。
素人ですのでEXCELのマクロの記録で作っていますが、データーフォームが開いた
後の操作は記録されないのでこの新規(W)ボタンが登録できません。
>>329 チョー無理やりな解決方法(笑)
話し半分ぐらいで見てください
タイミング(又はバージョン)によっては失敗するかもかも
失敗したらゴメンね
Sub 追加入力X()
Range("B2").Select
SendKeys "%{D}", Wait
SendKeys "O", Wait
SendKeys "%{W}", Wait
End Sub
以下のキーコードを送ってまつ
Alt+D ....... コマンドバーの データ(D)を開く
O ....... データ(D)の中の フォーム(O)を開く
Alt+W ....... 新規(W)を押す
331 :
330 :2010/09/24(金) 23:40:57
げっ いらんものが残ってた 正しくは Sub 追加入力X() Range("B2").Select SendKeys "%{D}" SendKeys "O" SendKeys "%{W}" End Sub でした
「ご足労」の使いかたこれで良いのか?
>>332 様
ありがとうございます。
ど素人の為に考えていただき感謝感激。
正にこれです。早速このマクロ式で”追加入力”ボタンを作りました。
332さんにとっては簡単な式でしょうけど、こう言った式は余り紹介されていません。
データーフォームを開いた後のマクロは書けない、と言うサイトの言葉通り
新規(W)ボタンの操作はマクロに記録されませんでした。
顧客名簿などはそのつど追加していくはずですしどうやって新規フィールドに
追加しているのか、、、その辺を調べてもちんぷんかんぷんでした。
素人であほかと思われるに違いないのに、快く答えていただきありがとうございました。
感謝感激雨霰、神様、またの機会がありましたら宜しくお願いいたします
続けての質問申し訳ありません。 項目 単価 数量 合計 領収金額 のタイトルの下にデーターが入っています。 データー→フィルター→フィルターオプションの設定で 領収金額の条件を0と空白セルにして抽出させたいのですが 抽出条件の式を 0 または = を単独で入れると領収金額セルが0または空白の時 それぞれ抽出は出来ています、 0または空白の時両方を同時に抽出させるにはどのようにすればいいでしょうか。 どうぞ宜しく。
2000です。
>>337 様
ご指導の通り条件範囲を2段にして指定したら
出来ました。
本当に助かります。ありがとうございます。
まだ質問したら怒りますか?
最後です。
A列(番号) B列(個数) C列(実個数)
1 1 5 4
2 2 4 3
3 8 7 6
4 A1 5 5
5 B1 3 3
6 9 7 6
のようにC列にA列が整数の場合だけB列の個数を-1したいのです。
この時C列のセルに入れる関数はありますか?
関数を調べてもさっぱりわかりません。
もしあるなら最後のお願いです。宜しくご教示を。
>>338 整数の場合だけって小数点付きの実数もあるのか?
だったら=IF(ISNUMBER(A1),IF(A1=INT(A1),B1-1,B1),B1)
単純に数値のとき-1なら=IF(ISNUMBER(A1),B1-1,B1)とか=B1-ISNUMBER(A1)
上に書き込んだ追加です。 =IF(ISTEXT(A8),IF(B8>1,B8)) で文字列の個数そのまま =IF(ISNUMBER(A8),IF(B8>1,B8-1))で整数の個数-1で計算できることまでは わかりましたが、この二つを結合することは出来ますか?
=IF(ISTEXT(A2),IF(B2>=1,B2),IF(ISNUMBER(A2),IF(B2>=1,B2-1))) で解決しました。 お騒がせすみません。
ここはVBAのスレじゃねーか
>>342 様
お見事、おそれいりました。
これを使わせていただきます。
ただ、なぜ-ISNUMBER(A2)だけで-1されるのかわからない、、、
でもとにかく感謝!
ど素人にお付き合いいただきありがとうございました。
また何かあったら(本当はいくらでもある)質問させてください。
TRUEかFALSEじゃないのか? で、Excelの数式で数値として扱われるときは、 TRUEが1、FALSEが0と変換されると思うのだが。 VBA等のBasic起源だと、偽は0だが、真は-1なので注意。
>>348 347じゃないが繰り返してないじゃん。
調べもしないでいきなり質問するやつって本当にいるんだな VBAでもねーし相当うぜー
無駄に繰り返しているな。
>>347 が何をどう突っ込みたかったのかわからん。思うのだが、なんだよ?
TRUEは1だって散々出てるだろ。
TRUEは0以外。具体的にいくつにするかはコンパイラ依存
あほか スレチな議論はもういいだろ
本当に数値の1か0しか返さないとすると、 セルの内容としてTRUE/FALSEが表示される理由が説明できなくなるな。
お前ら誰に説明してるんだ…?
Wokbook_Openとauto_open どちらもワークブックが開いたときに自動実行されるものだと 思ってんですけど、この2つの違いってなんです? またどういう使い分けをするんですか? 普段はauto_openを使っていはいるんですけど。
>>356 Excelを起動したときに動作するのがauto_open
ブックを開いたときに動くのがWorkbook_open
ブックをダブルクリックしてExcelの起動と同時に開いた時は両方が動く
358 :
デフォルトの名無しさん :2010/09/27(月) 17:43:18
>>357 レス、ありがとう。
な~んか、微妙な違いw
どういうふうに使い分けるんですか、それ?
auto_openなんて今じゃほとんど使わないよ。 excel95の時代には使うしかなかったから、その時代に作ったブックなんじゃないか?
360 :
デフォルトの名無しさん :2010/09/27(月) 18:28:35
>>359 そうなんですか。ず~っとauto_openにしてたけど、そしたらこれからは
workbook_open の方に変えていきます
先生おせーてください
A1に1、B1にTRUEとして=A1=B1とするとFALSEになります。
本当に
>>351 のいうようにTRUEは1なんでしょうか?
>>361 1は1、TRUEはTRUEだよ。
ただセルで加減乗除の計算するときTRUEは1にキャストされるんだよ。
=A1-B1=0みたく計算するとTRUEは1になる。
つまり
>>347 の言うとおりだ。
>>361 ワークシートの話を蒸し返すな。…お前わかって言ってるだろ
あの質問では1で正解なんだよ、TRUEが何であるかは状況によって変わるんだから
TRUEは1になり得るが、常に1であるわけでもなく、また1はTRUEになり得ない
True=-1が常に成立するVBAとは違う
>>361 どんな式にも、評価式と計算式がある事を理解して下さい。
「A1=B1」:評価式
「A1+B1」:計算式
で、TRUE/FALSEという値は、本来は評価式専用の「論理値」です。「数値」ではありません。
計算式内にはTRUEかFALSEか?という結果は生まれませんし、1をTRUEで割るとかいう事はそもそも出来ません。
ただ全部エラーとすると不便なので、計算式内に出現した場合に限りTRUEを1、FALSEを0として扱う事にしています。
A1とB1が一致しないのは、「評価式内で」TRUEと1を比較しているからです。
評価式内ではTRUEは常にTRUEという論理値であり、どんな数字とも一致しません。
(※ややこしい事に、VBAでは評価式内でもTrueは-1と常に一致し、Falseは0と常に一致します。
これはVBAでの解釈が数値を優先している事に起因します。
ワークシート式ではTRUE/FALSEを論理値と解釈するほうを優先しています。)
-----------
>>362 キャストって言葉を持ち出すのは混乱の元じゃないですかね。VBAにはない単語だから。
>>363 > TRUEは1になり得るが、常に1であるわけでもなく、また1はTRUEになり得ない
真実だけど理解されないんじゃ…けど文学的でカコイイw
365 :
361 :2010/09/28(火) 13:30:32
みんな謝謝 よくわかったアル 346の説明が下手ということも分ったアル
Excel2003です。 日付について If Not IsDate(TextBox1.Text) Thenと 日付以外の入力を拒否してるんですけど、 帳簿なので"yyyy/mm/dd"と年月日完全に入力させたいところ、 "yyyy/mm/"と月日でも日付と見られてエラーに出来ないので困ってます。 さらに If TextBox1.Text <> Format("yyyy/mm/dd") Then とか色々試したけど通じなかった・・・ "yyyy/mm/dd"以外を認めない方法無いですか?
>>366 すみません、
TextBox1.Text <> Format(TextBox1, "yyyy/mm/dd") Or Not IsDate(TextBox1.Text) Then
で自己解決しました。
動作をよく確かめてないので不具合出ない自信ないですけど(汗
368 :
デフォルトの名無しさん :2010/09/28(火) 17:13:18
すみません、教えてください。 Excel2007で以前のバージョンのVBAを開こうとしたら、 『現在インストールされていないコンポーネントが必要です、 VBAコンバータと検索してください』 てエラーが出ます。 マイクロソフトのサポートに電話したら、 無償じゃ教えられないと言われました。 2007で以前のバージョンのVBAを開けるようにするには、 どうしたらいいでしょうか?
EXCEL2007です。 A7に○と入力されている場合にF8~I8のセルを結合し、 そうでない場合は何もしないコードを教えてください
そんな簡単なことも分らんのかwww VBA慣れてる人はそう思うかもしれないが、 ググっても答えに辿りつかない
ifとmergeのヘルプを読んでみるといいよ 辿り着かない時はマクロの記録やってみるとmergeが出てくる
Sub Macro1() Dim range1 As Range If a7 = "○" Then Range("f8:i8").MergeCells = True Else End If End Sub このコードでおかしいところがあったら指摘お願いしますm(__)m
If a7 = "○" Then は If Range("a7").Value = "○" Then Range("f8:i8").MergeCells = True は Range("F8:I8").Merge でもいい
>>372 目くじら的な指摘を
Dim A7 As Range ’変数名間違い
Else 'この行はいらない(Elseは省略できる)
自動制御しなくていいならあとは正解
(該当シート開いてないと誤動作する可能性があるけど)
>>361 君にゃ叩く資格はないよ
375 :
デフォルトの名無しさん :2010/09/28(火) 18:36:41
VBAでエクセルの機能を使わないでソートをしたいと思っています。 調べてみるとVBAにはソートの機能がないので関数を作るようですが 多次元配列や構造体配列に対応したものってありますか? サンプルコードのあるサイトを御存知でしたら、教えてください。
>>374 A7の取得を指摘すんの忘れとったわ、すまんorz
>>376 対応もクソも、それ場合に応じて処理内容が変わるから
その形に合わせて基本形からハンドメイドするしかないでしょ
多次元だとどこを起点にどの方向に何回ソートしなきゃいけないかとか、
構造体では内部の変数名を取得する方法がないからオプションで処理すんのも無理だし
むしろソートが欲する形にデータ側を変形するのが手っ取り早いと思うが
378 :
368 :2010/09/28(火) 18:49:56
dll入れてVBA使えるようになった、 誰も教えてくれなくてちょっと悲しいわ (:_;)
>>378 くだらなかったからスルーしてた すまん
DLL…?
>>375 再帰処理使ってクイックソートを実装するのが一番良いと思う。
再帰処理?何それ?ってレベルならバブルソート実装から練習すると良いよ。
383 :
デフォルトの名無しさん :2010/09/28(火) 22:36:09
仕事でVBAを使ってかれこれ三年になるし、そろそろ自己満も込めて VBAプロフェッショナル(資格ね)に挑戦してみようと思うのだが。 ここにいる奴らの中で、合格した奴いる? 一人で満足してねーで攻略方法とか教えろよ。いや、教えて下さい。
アホか。 自分のために受ける試験なんだから 自分で考えて勉強しろ。
何もせず普通に受けたら合格してた 俺の職業、大工なんだけど…
386 :
デフォルトの名無しさん :2010/09/28(火) 23:48:23
Private Sub Worksheet_Change(ByVal Target As Range) Dim CN As ADODB.Connection, RS As ADODB.Recordset If Target.Column = 9 And Target.Row >= 8 And Target.Row <= 26 And Target.Row Mod 2 = 0 Then On Error Resume Next If Target.Value = "" Then Exit Sub Set CN = New ADODB.Connection Set RS = New ADODB.Recordset If CInt(Application.Version) <= 11 Then CN.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0" & _ "Data Source=" & ThisWorkbook.Path & "\該当ファイル.xls;" & _ "Extended Properties='Excel8.0;HDR=NO'" Else CN.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0" & _ "Data Source=" & ThisWorkbook.Path & "\該当ファイル.xls;" & _ "Extended Properties='Excel12.0;HDR=NO'" End If CN.Open Set RS = CN.Excute(Select * From [該当シート$] Where [該当シート].F2 = '" & Target.Value & "'") If RS.EOF = True Then ListForm1.Show End If Target.Offset(1,0).Value = RS.Fields(10).Value On Error Goto 0 RS.Close: CN .Close Set RS = Nothing: Set CN = Nothing End If End Sub
387 :
デフォルトの名無しさん :2010/09/28(火) 23:53:12
VBAマスターの皆様教えて下さい。 エクセルファイルのとあるシートから別シートにあるデータをADOを使って取得しようとしていますが、 上記↑のコードだと何故だかうまくいきません。(Excel2007以上だとうまくいく) ここではADOを使う必要がないのは分かっていますが、現在ADOを研究中なので気になって仕方ありません。 どなたかご教授いただけないでしょうか。よろしくお願いします。
>>387 適当に言ってみるけど、
Provider=Microsoft.Jet.OLEDB.4.0
の直後に ; がないとか
389 :
デフォルトの名無しさん :2010/09/29(水) 00:44:28
>>388 さっそくのお返事ありがとうございます。
「;」は記述し忘れです。申し訳ございません。
Target.Offset(1,0).Value = RS.Fields(10).Value
↑この部分でレコードセットのフィールドによっては
値を取得しているフィールドも存在するのですが・・・何故でしょう。
>>387 Select文の前に " が抜けてるとか。
>>387 望む結果がなんなのかわからないし、どういうふうに動作しないのかわからないので
なんとも答えしにくいですが、
まず、On Errorを外して実行。エラーがでなければ
If文の条件を疑ってみる。
それでも正しく動いているなら、
Target.Offset(1,0).Value = RS.Fields(10).Value
のあたりかなぁ。
いまのところこれくらいかな。
392 :
デフォルトの名無しさん :2010/09/29(水) 08:16:42
ActiveX Data Objects 2.8 Library が参照されていない、に1票 2007では「ActiveX Data Objects 6.0 Library」のはず
いや、でぇくならVBAで設計補助とかできるじゃん
EXCEL2000、XP PROでリストを作ってデータ(D)→フォーム(O)で入力をするに当たって 出てくるデーターフォームのダイアログの位置を同じ位置に固定する事はできますか。 ユーザーホームだと例題はたくさん見つかるのですが、、、。 データーフォームを出すマクロを作ってこの式の何処にどのような式を入れれば ダイアログの位置制御が出来るのかも合わせて教えていただけたらと思います。 Sub 入力画面() ' ' Macro1 Macro ' ' ' ActiveSheet.ShowDataForm End Sub
>>393 悪いが今時の大工の大半は図面も引かんし材料の手配もしないんだ
話が来た時にゃもうどっちも出来てるんで…
昔の現場じゃ大工が一番偉かったんだがなぁ はっはっは
処理速度について質問です。 VBAで4000行~6000行の1列のデータ内からキー値となる1000個のIDをマッチするものがあるか全部検索する場合、 FINDの関数と、Cellsで1行ずつひっかける場合ではどちらのが高速でしょうか?
測定すればいいのでは・・・
速度厨は他のスレでやってね
答えられないなら顔真っ赤にしないでスルーしろよキモピザどもw
>>396 そういうのはExcelがパフォーマンス上
最も苦手とする処理。
どっちでやっても実用的な速度は出ない。
悪いことは言わないからAccessでやりなさい。
どちらかと言われればfindだと思う
>>400 速度は期待出来ないですか・・・Access調べてみます。
>>401 データ数増えた場合気になっていたのですがFindでしたか・・・
お二人とも回答ありがとうございました。
実行速度なども調べてみます。
少々時間が無く質問してしまいました、気をつけます。
403 :
デフォルトの名無しさん :2010/09/30(木) 05:41:10
ADO使えば?メモリリークするけど
>>396 ,
>>402 FINDは関数じゃなくメソッドの間違いだろ?
文字列の完全一致検索だとして、FindメソッドやCellsで二重ループならそりゃ遅いだろうね。
ただしソートするとかDictionary使うとか工夫すればならその程度のデータ数じゃ一瞬だよ。
Excelが苦手ってわけじゃない。
まぁ、
>>400 はExcel=ワークシートで話してるようだが、
ここはVBAスレだからな。400にはコーディング能力がないでFA。
一般的にはVBAでセコセコとループを回すより ワークシート関数をずらっと並べた方が速い。 今回の案件だと、COUNTIFを千個並べれば済む。 何でもVBAでやるのではなく、場合によって 関数と使い分けるのが賢いExcelユーザーというもの。
オートフィルタが一番早いでござる
>>405 別にコーディングしなくてもIDをソートすりゃ一瞬だよ。
試しに100万データと20万のIDでVBAでやってみたら、データもIDもソートしてあれば2秒ちょい。
IDのみソートしてあれば5秒ちょい。
ソートのコストも考えなきゃいかんけどな。
Dictionaryは遅いから却下。
>>406 上のデータ数でやってみて。
COUNTIF使うのは賢くねーな。
彼には理由あってVBAで処理しようとしている、 そんな可能性は考慮してやらんの? あと2000個だろ。
上の2秒ちょいとかは一致したら隣にTRUEと入れる時間な。
>>408 君は何か問題を取り違えてると思う。
ExcelのVBAでループを6000×1000回も回して
数秒で終わるわけがない。
今回の問題に関しては、VBAの出る幕はないよ。
セル上の大量のIDとやらがセルになくても良い可能性は?
>>411 ソートしてからのマッチングアルゴリズムとか知らんの?
バイナリサーチも当然知らないんだろうなぁ。
6000*1000回なんてとんでもないよ。
>>413 データが6000個で
キーが1000個あるんだから
キー一個についてデータ6000個との比較が必要なのは
当たり前じゃん。
君は何か勘違いしている。
ありゃやっぱ釣りだったか。
>>415 冗談はよそうぜ
配列を2つ用意、まずワークシートのデータを全部読み込んで、 ループしながら判定結果をもう一つの配列に入れてって、 全部終わったら結果だけを一気にワークシートに書き込む 最近のマシンならほぼ一瞬で終わる
釣り確定だな。 そもそも6000×1000程度ならVBAで配列の二重ループで1秒ちょいだもんな。
>>418 6000×1000程度ならね。
データが多ければそんな単純な方法では駄目だな。
何秒かなんて性能によりけり、求める実用速度も然りだからみんな秒での表現はやめれ Pen2 200MHz換算で、という話なら全面的に賛同しよう
じゃあCore i7、DDR3-16GB、64bit版、300MB/sのSSDを基準にしましょう
2000行から1000個のキーだろ。 行内の個数は言及してないから不明。
425 :
デフォルトの名無しさん :2010/10/01(金) 00:49:20
あるファイルで10個ぐらいあるシートをひとつずつデータ行を全部コピーして 別の指定したファイルの同じシートの縦に順番にペーストするマクロがあるのですが これが10シートぐらいあるとだいたい10秒ほどかかります。 これ Window("aaa.xls") Window("bbb.xls") で一回一回繰り返し繰り返し切り替えるのが結構時間がかかるみたいなんですが これ全部コピー元のデータをすべて一旦配列にして格納して Window("bbb.xls")で一気に出力していくのでは どちらがパフォーマンスとして高いですか? 作成してもいいのですがやった結果、結局時間は変わりませんでしたってのがアレなんで… もしくは上記の事をしたい場合に こういうやり方が一番いいってのがあれば教えてください
>>425 何を言ってるのか分からんからちゃんとソース見せろ
結局ファイルロードにかかってるオーバーヘッドじゃないの?
シート内の元データはいくつで、結局合計いくつだ?
先のワークシートは複数なのか?
>>424 まぁ…そう取れなくもないなw
でも主は行番号じゃなく行の総数を書いてるんじゃね?
>>425 10秒ぐらいなら別にいいじゃん
そんなに大急ぎでデータのコピーをしなきゃいけないの?
VBAを勉強したてで、一人ではなかなかうまくいかなので アドバイスお願いします。 【目的】 複数の特定セル(セルE10とE11とE12)の内容をテキストファイルに書き出したい <最終希望のテキスト表示> 1行目)セルE10の内容 2行目)セルE11の内容 3行目)セルE12の内容 【現状】 Sub test01 () Dim txtmei As String Dim newtxtstr As String Dim FSO As Object Dim f As Object newtxtstr = ActiveSheet.Range("E10:E12").Value txtmei = "C:\test01.txt" Set FSO = CreateObject("Scripting.FileSystemObject") Set f = FSO.CreateTextFile(txtmei) f.write newtxtstr f.Close Set f = Nothing Set FSO = Nothing End Sub >newtxtstr = ActiveSheet.Range("E10:E12").Value まず、ここでエラーになります。 強引に埋め込んだ感じの記述で申し訳ないですが、 アドバイス宜しくお願いします。
>>428 newtxtstrはString型、ActiveSheet.Range("E10:E12").ValueはVariant型の2次元配列。この型は代入ができない 。
解決方法は色々あるけど、とりあえずnewtxtstrを右辺と同じVariant型にする方法。
あと、ファイル出力の部分はもうちょっと簡単な方法に変えさせてもらった。
Sub test01()
Dim txtmei As String
Dim i As Integer
Dim newtxtstr As Variant
newtxtstr = ActiveSheet.Range("E10:E12").Value
txtmei = "C:\test01.txt"
Open txtmei For Output As #1
For i = 1 To 3
Print #1, newtxtstr(i, 1)
Next i
Close #1
End Sub
430 :
428 :2010/10/01(金) 02:25:55
>>429 レスありがとうございます!
なるほど、左辺と右辺がちぐはぐだったわけですね。
そろそろ時間も時間なので、起きたら試してみます!!
画面の自動更新を停止して内部処理をして完了したら自動更新on これを繰り返すプログラムを作ったのですが、画面が更新する場合としない場合が発生します。 解決方法ご存知の方おりましたらご教授下さい。
application.screenupdate = false 処理 application.screenupdate = true を挟んでて、更新されないと言うのは、目的の処理がされないって事? それとも、挟んでる筈なのに更新される時とされない時があるって事?
433 :
428 :2010/10/01(金) 20:14:36
>> 429 報告遅れましたが、 無事に思い描いた通りに出来ました。 ありがとうございます^^
434 :
431 :2010/10/01(金) 20:45:13
Application.ScreenUpdating = False Application.Calculation = xlManual 処理 Application.Calculation = xlAutomatic Application.ScreenUpdating = True Range("A2:G9001").Sort Key1:=Columns("E") で無限ループしてますが処理自体はきちんとやっているようですが、 ソートする場合としない場合があるみたいです。 説明わかりづらくてすみません。
>>434 ExcelとWindowsのバージョンは?
9000行のソートを無限ループだとメモリリークとか起こしそう
436 :
431 :2010/10/01(金) 20:55:48
Excel2007でxpです。 メモリ4ギガ積んでいますが動作中、特に警告とかは出てきません。
>>436 途中でブックやシートの切り替えやってる?
あと、ループ何回目でおかしくなるとか調べた?
438 :
431 :2010/10/01(金) 22:10:06
ブックは同じですがシートの切り替えは行っています。 ループ回数は調べてませんがおかしくなる場合は数回目でソートしなくなりそれ以後ずっとソートしない感じです。 ただ、6時間程度ループし続けても正しく動作する時もあります。
>>431 xlAutomaticって代入したその瞬間に強制計算入るっけ?
DoEventsを直後に入れてみたら処理するんじゃないかな?
今試せないから確かめられぬ
ああそうか、許可しただけじゃ画面が変化しない可能性があるのか 強制的に再計算させるのはApplication.CalculateFullだから、以下のように修正するといいのかな Application.Calculation = xlManual ' この行はループの外に出す ' ここからループ Application.ScreenUpdating = False 処理 Application.CalculateFull '再計算を実行 Application.ScreenUpdating = True Range("A2:G9001").Sort Key1:=Columns("E") ' ここまでループ Application.Calculation = xlAutomatic ' この行はループの外に出す
間違えた。この順番じゃないとダメか Application.ScreenUpdating = False Application.Calculation = xlManual 処理 Application.Calculation = xlAutomatic Application.CalculateFull ' 再計算を実行 Range("A2:G9001").Sort Key1:=Columns("E") Application.ScreenUpdating = True
442 :
431 :2010/10/01(金) 23:01:57
>>439-441 ありがとうございます。
教えてもらった方法を試してみます。
またなにかありましたらよろしくお願いします。
443 :
439 :2010/10/01(金) 23:29:18
CalculateFullってのがあったのか、勉強になった サンクス
444 :
デフォルトの名無しさん :2010/10/02(土) 00:21:51
指定した時間になったら動くようなプログラムを作りたく 拾ってきたコードで下記の様にしてしてみましたが CPU使用率が50%くらいになってしまいます。 これってあまりいい例ではないのでしょうか? Do While Now < targetTime DoEvents If stopFlag = True Then Exit Do Loop 処理
445 :
デフォルトの名無しさん :2010/10/02(土) 01:26:50
sleepいれれば? タイマーイベントってなかったっけ?
>>444 時間になったら処理開始はApplication.OnTimeを使う
>>445 SleepはDLLをインポートしないと使えない
あと、やっぱりCPU食うしSleep中はExcelがまったく操作できなくなる
447 :
デフォルトの名無しさん :2010/10/02(土) 01:44:15
>あと、やっぱりCPU食うしSleep中はExcelがまったく操作できなくなる そうなんだけど、1msでいいじゃん
バイナリサーチというのを見つけたので試しているのですが、 例えば、A列、B列に下記データがあるとします。 【シート1】 【シート2】 1 りんご 1 2 みかん 99 10 もも 15 などでマクロ実行 15 ばなな 99 さくらんぼ シート2にシート1のA列の番号入れて、マクロ実行すると シート1のB列~数列のデータを引っ張って来る目的です。データ量はシート1が4万前後、シート2が1000~5000 拾い物のバイナリサーチの関数をいじって見ましたが、一致したデータの行番号の取得が出来ません。 下記コードなのですが、何かアドバイス頂けませんか。 文字数規制のため、次のレスに貼ります。
Private Function BSearchList(st As Long, rowMax As Long) As Long ''''' 引数 ⇒ A列のID、最大行数 ''''' 見つかった場合、戻り値は行番号に出来ればと思っています。 Dim nextpos As Long Dim lastpos As Long Dim minpos As Long Dim maxpos As Long BSearchList = -1 minpos = 0 maxpos = rowMax Do nextpos = (maxpos + minpos) \ 2 '最後まで見つからなかった If lastpos = nextpos Then Exit Do '見つかった場合 If st = nextpos Then MsgBox nextpos BSearchList = nextpos Exit Do '見つからない場合 Else '対象IDが 半分より小さい If nextpos > st Then maxpos = nextpos '対象IDが 半分より大きい Else minpos = nextpos End If lastpos = nextpos End If Loop End Function
>>448-449 元々Excelにはバイナリサーチの関数は備わっているけどね。
アルゴリズムのお勉強なら、よく見かける下手なアルゴリズムなら下だ。
上手なやつは教えない。
初心者向きにRange型を使った。
ユーザー定義関数なら=BS(A1,Sheet1!A$1:A$50)のように使う。
Function BS(a, b As Range) As Variant
Dim c&, d&, e&, f
d = 1
e = b.Count
Do While d <= e
c = (d + e) \ 2
f = b(c)
If f < a Then
d = c + 1
ElseIf a = f Then
BS = c
Exit Function
Else
e = c - 1
End If
Loop
BS = CVErr(xlErrNA)
End Function
If~Then~Else~End If構文において、 Thenの時だけ処理して Elseの時に何もせず次に進む処理は どう書くのがセオリーですか? 今はElseとEnd Ifの間に「何もしない」という コメント行を入れているのですが、 何か間抜けな気がして仕方ありません。
>>452 Elseを書かないと、Thenの次の一行だけが
有効になって二行目以降からEnd Ifまでの処理は
Else扱いになると聞いたことがあるのですが、違いますか?
かいてみろよ
>>453 んなわけねーだろ?
人に聞くより自分で試してみろよ。
sub hage()
if 2 > 1 then
msgbox "2は1より大きい"
msgbox "禿げ"
end if
end sub
"禿げ"までいくだろ?
>>448-449 です。
>>450 さん
バイナリーサーチのご提示ありがとうございます。
思っていた通りな感じになりました。
自分の書き込んだ物もどこが違ったか少々いじったりしてみます。
ほんとありがとうございました!
>>456 お前は
>>396 か?
少ないIDの方からデータを検索するのかよ。
俺は逆かと思ったぜ。
40000と5000程度じゃExcelの備え付けのバイナリサーチなら一瞬だな。
何も工夫しない普通のVLOOKUPでも1秒程度だからデータが少なすぎるってもんだぜ。
458 :
デフォルトの名無しさん :2010/10/02(土) 22:29:36
a
>>451 ,
>>452 > Elseを書かないとThenの次の一行だけが有効になって二行目以降からEnd Ifまでの処理はElse扱いになる?
そういう挙動はしない。
が、1行If構文という特殊な書き方ならある。
これを伝言ゲームしてるうちに意味不明な解釈にいたったのかも。
IF構文には2種類あり、みんな知ってる複数行で書く方法と、構文全体を1行で書く方法。
つまりThen に続けて改行せずに何かコードを書くと1行If構文になる。
この場合ElseもEnd Ifも書かない。(書くとエラーになる)
その挙動はIIF構文に似た動きになる
(True節として1行だけが有効になるが、2行目以降はIfのスコープ外になる)
同じデータがあった時はどうすんだろ?
>>459 の補足。
例1:
If 1 <> 1 Then
MsgBox "Hoge"
End If
MsgBox "Nyoro"
例1は常にFalseでNyoroしか実行されないコードだが、これを1行Ifで書くと例2のようになる。
例2:
If 1 <> 1 Then MsgBox "Hoge"
MsgBox "Nyoro"
1行If構文の場合、Then ~ 改行までがTrue節として扱われる。
Ifのコード全体を短く書けるので、簡潔な条件、簡潔な処理の場合に重宝する。
ただしElseは書けない。Else節を書きたい場合は普通のIf構文で書く必要がある。
(というかそもそもTrue節だけあればいいシンプルなコードのために用意されている)
また1行IfのTrue節は「改行」までなのでコロンを入れれば複数コードも書ける。(例3)
コロンを使うと通常のIfもよく似てくるので注意(例4)
例3:
If 1 <> 1 Then MsgBox "Hoge": MsgBox "Huga"
(常にFalseのためHogeは実行されないが、改行までがTrue節のためHugaも実行されない)
例4:
If 1 <> 1 Then: MsgBox "Hoge":Else: MsgBox "Huga"
(常にFalseのためHogeは実行されないが、Else節のHugeは実行される)
462 :
デフォルトの名無しさん :2010/10/02(土) 22:46:05
【質問】C3:G1202の範囲で0以下が入力されてたら1と表示するようにしたい Private Sub Worksheet_Change(ByVal Target As Range) If Intersect(Target, [C3:G1202]) Is Nothing Then Exit Sub For Each c In Target If c < 1 Then c.Value = 1 Next End Sub だけどこれでは未入力も0と同じ扱いになるので区別したいです。 方法教えてくださいm(__)m
463 :
461 :2010/10/02(土) 22:52:51
1行IFでのElseの正しい書き方は下記だった、ごめん。 ゆえに「Elseが書けない」ってのは嘘。 俺もまだまだだな。 If 1 <> 1 Then MsgBox "Hoge": MsgBox "Huga" Else MsgBox "Nyoro" (HogeとHugaはTrue節、NyoroがElse節)
FileSystemObjectとかで、フォルダ内のファイル日付やサイズといったプロパティで 上位(下位)n位まで取得、ってどうやって処理するのがセオリーでしょうか? シートに転記しないとしたら、ソート自前で実装しないと無理ですか? スマートに処理できる方法はありますですかね
465 :
デフォルトの名無しさん :2010/10/02(土) 23:20:27
荒らし要請ならスレ間違いだぞ
>>464 「あるフォルダ内で日付が新しい順や、サイズが小さい順で
任意の条件、任意の数を取得」…って事か?
FSOではそのフォルダの中身をすべて列挙できるが、
条件付きで列挙する方法はないだろ。
細かい選別は自前で1つずつチェックしないと。
>>462 IsEmpty関数で未入力かどうか調べればいいんじゃね?
ユーザーが0を入力しているのか、Emptyが値0に変換されてるのかを。
IsEmptyはセルが未入力ならTrueになる。
470 :
462 :2010/10/02(土) 23:34:46
解決しました
471 :
デフォルトの名無しさん :2010/10/02(土) 23:46:29
下記のマクロを実行しても何も起こらず終了してしまいます。 期待するのは、UTF-16形式の文字列がA1セルに表示されることなのですが 分かる人いませんか Option Explicit Sub Readfile() Dim Stream As ADODB.Stream Dim sText As String On Error GoTo Err sText = "あいう" Set Stream = CreateObject("ADODB.Stream") Stream.Type = adTypeText Stream.Charset = "UTF-16" Stream.Open Stream.WriteText sText ActiveSheet.Range("A1").Value = Stream.ReadText Stream.Close Set Stream = Nothing Exit Sub Err: Set Stream = Nothing MsgBox (Err.Description) End Sub
>>460 誰への独り言?
もし
>>450 あてならexcelみたいに重複したら最後のやつにするのは簡単。
だが教えないと書いたとおりだ。
464は後だったorz
>>471 考え方がおかしくね?
"あいう"をUTF-16に変換して、それをCellに放り込んだら文字化けすると思うんだが。
>>471 のやりたい事と"あいう"は関係ないんじゃね?
最終的にUTF16のテキストファイルを読みたいんだろ、多分
477 :
464 :2010/10/03(日) 05:11:35
おはようございます
>>467 ttp://okwave.jp/qa/q2965710.html 例えばこんな感じでDateLasteModifiedを比較していけば
最新や最古のファイルは求められますが、次点以降のものはどう処理していけばいいでしょう?
一位のファイルをSetして以降、n回ループを回してチェックしていくには
コードをどう書けばいいのかが解りません…
取りあえず同時刻ファイルのチェックは置いておいてOKなんですが
>>471 とりあえず、ReadTextの前にPosition=0しないと文字列は取れない。(0バイトになる)
なぜUTF-16を扱いたいの?
UTF-16も厳密にはUTF-16/UTF-16BE/UTF-LEって3種類のバイナリがあるし、
(BE、LEにはBOMが付かない、UTF-16はBOMがあってもなくても可、BOMなしの場合はBE扱い)
わかんないので以下VBA標準のUnicodeと仮定してます。(MSの言うUnicodeとはUTF-16LEで、メモリ上ではBOMなし)
ADODB.Streamの解説して欲しなら書く(そんなに詳しくない)けど、前提がすでに勘違いしてない?
UTF-16のテキストファイルを、OpenステートメントのFor Inputで読んだりしてないよね?
あれはShiftJIS専用だよ。
Openでテキストとして読み込んでるなら、勝手にS-JIS→Unicode変換が行われちゃう(OpenはS-JISが前提)ので、
得体の知れない文字コードに変換され結果的に文字化けしてる。やり方がそもそも間違い。
(その場合はStrConv関数のvbUnicodeを2回実行すればなんとか元に戻ると思うが確実に戻るわけじゃない)
目的が「Unicodeのテキストファイルを読みたい」のであれば、Openでバイナリとして読み込んで
そのバイト配列をそのままString型変数に代入するだけで完了。ADODBいらない。
(VBAのString変数の中身と一緒なのだから変換なんて不要)
ADODB.Streamを使うのはS-JISとUnicode以外の様々な文字コードに対応したい場合で、
Unicodeしか使わないって状況なら、苦労して利用する価値はないと思うんだが。
>>477 取得したい数の配列を用意して、
そこに必要な条件に従った並びを維持する形で突っ込んでいけばいいだろ。
配列から溢れた分は捨てていけば最終的に目的のものが得られる。
480 :
467 :2010/10/03(日) 09:36:06
VBAをある程度組めるようになった人が躓くのって、再帰処理なのかな。
あぁ、それはあるかも。 現実世界とはちょっと違った考え方だからかな。
再帰処理でつまづいてます・・・。VBA歴3年
484 :
471 :2010/10/03(日) 10:52:41
>>478 >とりあえず、ReadTextの前にPosition=0しないと文字列は取れない。(0バイトになる)
助かります。とりあえずできました。
>なぜUTF-16を扱いたいの?
やりたいことは文字コードから文字への変換です。
文字コードはUTF-8, UTF-16(BE, BOMなし), Shift-JISです。
たとえば、S-JISの文字コード"89708940"(文字列)を"英院"(文字列)に変換したいです。
うまくいきません(下記
>>485 のソース)。
何が間違っているのでしょうか。そもそも、できるのでしょうか。
すいませんが助けてください。
485 :
471 :2010/10/03(日) 10:53:44
Option Explicit Sub Readfile() Dim Stream As ADODB.Stream Dim sText As String Dim sInput As String Dim sTemp As String Dim i As Integer Dim bCode(100) As Byte Dim iLen As Integer On Error GoTo Err sInput = "89708940" '(S-JISで"英院"を表す文字コード) iLen = Len(sInput) Set Stream = CreateObject("ADODB.Stream") Stream.Open Stream.Type = adTypeBinary '文字コードをバイナリモードで書き込み Stream.Position = 0 i = 1 Do Until i > iLen sTemp = Mid(sInput, i, 2) bCode(i) = Int("&H" & sTemp) i = i + 2 Loop Stream.Write bCode
486 :
471 :2010/10/03(日) 10:55:09
// 485のつづき '↓ここで'このコンテキストで操作は許可されていません'エラーとなる Stream.Type = adTypeText 'テキストモードで読み込んで文字コードを文字に変換 Stream.Position = 0 Stream.Charset = "Shift-JIS" ActiveSheet.Range("A1").Value = Stream.ReadText Stream.Close Set Stream = Nothing Exit Sub Err: Set Stream = Nothing MsgBox (Err.Description) End Sub
>>485 ,
>>486 ADODB以前に、突っ込みどころが満載だわ…。
まず配列は(0)が最初だぞ。
このコードだと(1)から書き込んでるから、先頭に1バイト余計なものが出来てる。
で、2文字切り出して配列に入れるのはいいんだが、
iは2ずつ増えてるから、間違えた位置に代入してる。
(配列の中身が1つずつ空白になってる)
あと動的配列のほうがいいんじゃないか?とか
Until気持ち悪いからWhileのがいいっていうかそもそもDoよりForのほうが適任とか
ってことでとりあえず先頭部分のコード書き換え例。
Dim Stream As ADODB.Stream
Dim sInput As String
Dim i As Integer
Dim bCode() As Byte ’動的配列に変えました(いらない変数も消しました)
sInput = "89708940" '(S-JISで"英院"を表す文字コード)
For i = 1 To Len(sInput) / 2 '文字数の半分だけループ(結果となる配列側の総数を基準と考える)
ReDim Preserve bCode(i - 1) '動的配列の拡張 (0ベースなので-1)
bCode(i - 1) = "&H" & Mid(sInput, i * 2 - 1, 2) 'iの2倍数(2,4,6,8...)から1引くと奇数(1,3,5,7...)になる
Next
488 :
487 :2010/10/03(日) 12:07:58
つーかS-JISのテスト文字列を作るのだったら bCode = StrConv("英院", vbFromUnicode) これ1行だけでおしまいなんだけどね。 もともと"89708940"みたいな形で保存されてんの?
489 :
487 :2010/10/03(日) 12:12:38
えー次、ADODBの部分。 1行足したら動いた。 Stream.Position = 0 '←ここを追加しました Stream.Type = adTypeText 以上。
490 :
487 :2010/10/03(日) 12:37:14
491 :
471 :2010/10/03(日) 12:43:14
>>487 さん
スバラスイ。ありがとうございました。
あと、質問で書いたコードは指摘のとおりひどいものでした。
こっちでも別のやり方でいちおうできたんですが、
487さんのやり方のほうが良さそうなので、これでいきます。
ひとつだけ言わしてもらうと、
For i = 1 To Len(sInput) / 2
の部分、これだとループが回るごとに毎回Lenがコールされるので
計算コストがかかりすぎる。
大量の文字コード変換処理を行うには不向きなので
iLoopMax = Len(sInput) / 2
For i = 1 To iLoopMax
に訂正します。
>>もともと"89708940"みたいな形で保存されてんの?
はい。そうです。
BasicのFor文は終了値を最初の一回しか評価しないから、 放っておいても大丈夫、だったよね?たしか。
>>491 Lenの部分が計算されるのは1回だけです
わかりやすい例を用意したので、For~Nextの基本動作を確認してみてください
a = 10
For i = 1 To a
Debug.Print i
a = 5
Next
ReDim Preserveってアホか? ループに入る前に確保しろよ。
495 :
471 :2010/10/03(日) 13:07:25
>>493 確認しました。そうなんだ。
どこかでループの終了判定でLenを使うと莫大な計算コストがかかると
いう話を聞いたけどな。Do untilのときだったかな。まあいいや。
VBA勉強初めて何年ですか?
498 :
487 :2010/10/03(日) 13:46:26
>>491 ,
>>495 そうそう、そりゃDoの場合よ。
あっちは毎回判定を実行する。
それと、こういう作業するなら「イミディエイトウインドウ」の使い方覚えるといい。
ググってみ。変数や配列の中身をリアルタイムにチェックできるようになるから、
今回のようなミスを自分で簡単に発見できるようになるぞ。
お前さんはいい師匠に巡り会えたら伸びる子だと思う。ガンガレw
>>494 ,
>>497 確かにループの外で良いね。直すの忘れてたよ。
コード書き換えてる最中に付け加えてそのままだった。
だがあれで鬼の首取ったつもりの君はいい師匠に巡り会えなかったようだなw
>>495 ステップ実行すりゃ分る。
おまいさんの言うとおり下なら何度もlen(文字列)を取得する。
do until i =len(文字列)
i=i+1
loop
VBのString型変数には文字列長がヘッダーに付いてるから莫大なコストじゃねーけどな。
文字列長が付いてない言語なら莫大かも知らんけど。
いい師匠w ループの中でやらないのは猿でも知ってるぞ。
キーキーうるさい猿だなぁ
その猿以下だもんなぁ...
いいぞもっとやれ
504 :
487 :2010/10/03(日) 14:25:39
俺にはいい師匠がいなかったって事だよw つか全部趣味の独学だわさ この流れもうやめれw
出どころがきちんとしたPGだったら、こんなとこで質問なんかしないっつうの。 マクロ使えるようになった事務員の次のステップとか、職業PGが社内ツール 作ったりする時のお手軽な言語なんだから。
506 :
471 :2010/10/03(日) 15:04:37
みなさんありがとうございました。 S-JIS, UTF-8の場合はそのまま変換できましたが、 UTF-16の場合は入力文字コード(文字列)をLEでADODBに書き込まないと文字化けしました。 0031(UTF-16,BE) -> 文字化け 3100(UTF-16,LE) -> '1'に変換 BEで入力してできる方法もあるのかもしれませんが。
皆必死になって調べまくりで答えてんじゃね~の。
…バカか? 元々UTF-16LEであってUTF-16じゃないってだけだろ? 自分で何をしゃべってるか理解してんのか?
>>506 UTF-16という呼び方は、BEとLEを含めた総称として使われることもあるけど、
厳密には違う意味があるのよ。そこんとこわかってる?
文字コードの規格名としては、UTF-16、UTF-16BE、UTF-16LEはそれぞれ別物なんだわ。
UTF-16BEとLEの違いについてはもうわかってるでしょ?
それに加えて先頭に2バイトのBOMを付けられるのがUTF-16。
付いてるBOMがBEを示していれば、3バイト目以降がUTF-16BEそのもの。
LEを示していれば、3バイト目以降がUTF-16LEそのもの。
さらにBOMなしも許されていて、その場合は1バイト目から全部UTF-16BEそのもの。
UTF-16として読ませると化けるって事は、
バイナリの先頭にBOMがない上に中身がLEでしたって事だよ。
つまりその文字コードの規格名はそもそも「UTF-16LE」だわいな。
なんだこの状況?
鬼畜の集まりだな。 まあ、実際にまともな知識持ってるのは少数だな。
だわいな?
実際、日常生活でUTF-16のテキスト文書を アプリで処理する機会なんてあるの? あまり機会のないことに頭を悩ますのは 時間の無駄と思うんだけど。 人生他にやることいっぱいあるし。
そりゃ機会のない人にとっては時間の無駄でも 機会のある人にとっては死活問題となることすらある。
517 :
234 :2010/10/03(日) 20:05:00
その節は大変お世話になりました。
宿題は無事に受理されました。
>>243 ,
>>247 ,
>>251 ありがとうございました。
ですが、新たな課題が出されてしまいました…(´・ω・`)
[前提] セルA1には、以下のような文字列が入っています。
---------------------------------------------------------
ガム ??????-???
キャンディ ??????-???
クッキー ??????-???
チョコレート [??????-???]
ポテトチップス【??????-???】
---------------------------------------------------------
※ ??????-???は、お菓子を識別するコードです。
[問題] セルA1の??????-???部分のみを抜き出し、B列(B1から下方向)に
セル1つにつき、1つの??????-???を出力して下さい。
どうかお助けを…(´;ω;`)
?の取りうる値の範囲は?
519 :
デフォルトの名無しさん :2010/10/03(日) 20:57:11
1:左から空白文字を探して、 2:そこから後ろを切り出す ワークシートの関数でも出来るだろ、これくらい
>>517 Sub 妙な課題()
a = Split(Range("A1"), Chr(10))
For i = LBound(a) To UBound(a)
Cells(i + 1, 2) = Mid(a(i), InStr(a(i), "-") - 6, 10)
Next
End Sub
521 :
520 :2010/10/03(日) 21:02:32
ちょっと訂正。Option Base対策 Sub 妙な課題() a = Split(Range("A1"), Chr(10)) r = 1 For i = LBound(a) To UBound(a) Cells(r, 2) = Mid(a(i), InStr(a(i), "-") - 6, 10) r = r + 1 Next End Sub
522 :
520 :2010/10/03(日) 21:05:11
何度もごめん
Splitは常に0からの配列を返すので
>>520 で大丈夫でした
いや、宿題なんだから自分でやらせろよ。 ヒント書くのは構わないと思うけど、解答書くのはどうかと思うぞ。
pattern = ".{6}-{3}" で切りださせるとか、それくらいのアドバイスで良いんだよ。
>>524 それはヒントにならないよ。
前の課題から変わったところって
切り出した文字をセルに書き込む部分だけだもの。
つまりこの人は、ExcelVBAでのセルの指定方法すら
わかってないってことで、君の考えているレベル以前の
話なんだよ。
先生です。見てますよ。
私も見てます
質問です 指定セルの範囲をループさせてAという文字がある場合 そのセルの前2行を追加し、その後ろの行を2行削除するマクロを組んだ ところが無限に行を追加してしまう ループはFOR文でやってる。行を追加するだけだとまた同じ文字がヒットして追加されてしまうだろうけど 削除してるのになぜうまくいかないんだろうか
ループで削除させる時は↓から↑にstep -1 で進めるのが基本。
>>529 そうなんですか
下から検索して処理するのは微妙な気がするexcelのフォーマットなんですよね
削除と追加を同時にやってるのも良くないのかなぁ
数字ばっか処理してたから頭痛いわ
For cnt=30 to 3000
ループは1列しか見てないのでcntは行になる
検索する処理
ヒットしたら、その上の行を2行追加
その下の行2行を削除
next cnt
ステップ実行しろよ 理由なんてすぐわかるだろうに とりあえず、そのcntってのは行のRangeなのか?単なる数字なのか? 単なる数字なら、そりゃループ終わるまで増え続けるだろうよ
>>529 言いたいことはわかるけど、これは「下からでおk」じゃ済まないよ
面倒なことに「対象位置の前後両方を追加削除」してるので
どっちからループしたとしても補正処理が必要になっちゃう
>>530 ある"全体"を順次処理中に、現在処理中の位置より上に何か増えたらズレが生まれるでしょ?
"全体"そのものが伸びちゃって終了位置を変えなきゃいけないし、
現在位置のほうも増えた分だけ下にずれることを意識しなきゃ
For i to Maxでいうと、Maxとiの値をそれぞれ操作しなくちゃいけない
けど、ループ内ではMaxの値を操作する事はできない制約があるので、Forでは実現出来ないの
この場合はDo Untilを使い、上記のズレを自力で補正しながらループしてください
ちなみに終了行をオブジェクトで所持しておけば行挿入や削除によるズレを勝手にカバーしてくれるよ
(事前に終了行のRangeオブジェクトを持っておけば、前方行が挿入/削除されても影響されない)
>>532 の訂正
この場合Forでも可能でした、ごめんなさい
(追加数と削除数が同一なので、結果的にMaxが変動しないため)
ただ「終了行をオブジェクトで~」にはDoが適してます
>>528 Aが前後二つ以内にあったらどうすんの?
たとえば続いたらどうしたいの?
536 :
デフォルトの名無しさん :2010/10/05(火) 08:06:37
>>531 cntは行数です
>>532 やはり補正が必要ですよね
その確信が得たかったので助かりました
>>534 あの文章から見事に理解してます
流石です。おっしゃる通りの事がやりたいのであります
>>535 ヒットしたAの前後2行に別のAがヒットする事はありません
説明不足ですいません
仕様は
>>534 様の通りです
>>536 行の挿入や削除はしないのが基本だ。
こうすればよい。
一つ上か二つ上がAじゃないものをフィルタオプションでいったん抽出して、抽出した範囲に作業列を設け
下のような番号を振って作業列でソートする。
下は抽出してから番号を振ってる例だ
TITLE 作業列
A 1
B 2
C 3
C 4
A 5
F 6
G 7
0
0
4
4
すまん最初の4が左にずれたな。 とにかくAの右の番号から-1したものを下に2個ずつ書くということだ。
539 :
536 :2010/10/05(火) 10:36:59
解決しました!
4列 目 の 50~ 3000行 が 対 象
For Rows 1 = 50 To 3000
If re19.Test (Cells( Rows1 , 4 ).Value )= True Then
Application. CutCopyMode =False
' 2 行 追 加
Range (Rows 1 & ":" & Rows1 +
1 ) .Insert
Rows 1 = Rows 1 + 3
' 表 の 後 の 行 を 2 行 削 除
Range (Rows 1 + 27 & ": " &
Rows 1 + 28) .Delete
End If
Next Rows 1
27行とかは適当にre19(検索文字列)に
ヒットしない事がわかっているので決め打ち
>>537 どうしてもマクロじゃないとダメだったんです
でも勉強になります。有り難う!
>>539 本当に解決したんかな
これ、そのままコピペしても動かないよね
541 :
534 :2010/10/05(火) 11:39:35
>536,539 あれ?仕様は>534のとおりって言ってたのに、削除行が27~28行も離れてるの? それに、2行削除のときにRows1を+3してるけど、For~Nextループでさらに+1カウントアップするから判定しない行が存在するんじゃないの? 一応、>537さんの 行挿入/削除ではなくてソートキーを設定 という方法で作ってみました。 Dim tate1 As Long, tate2 As Long, tate3 As Long, n As Long Dim yoko1 As Integer, yoko2 As Integer, const_max As Long Sub ex528() yoko1 = 1 : yoko2 = 4 ' 判定列位置(A列): 作業列位置(D列) tate1 = 30 : tate2 = 49 ' 処理対象行の初期値 : 処理対象行の最大値 tate3 = tate2 + 1 ' 挿入行のソートキー書き込み行位置の初期値 const_max = 99999 Do If Cells(tate1, yoko1).Value Like ("*A*") Then Cells(tate3, yoko2).Value = tate1 - 0.5 ' 挿入行のソートキー書き込み Cells(tate3 + 1, yoko2).Value = tate1 - 0.5 tate3 = tate3 + 2 Cells(tate1, yoko2).Value = tate1 ' 処理対象行のソートキー書き込み Cells(tate1 + 1, yoko2).Value = const_max ' 削除対象行のソートキー書き込み Cells(tate1 + 2, yoko2).Value = const_max tate1 = tate1 + 3 Else Cells(tate1, yoko2).Value = tate1 tate1 = tate1 + 1 End If Loop Until (tate1 > tate2) End Sub 行削除・挿入を伴わないので、何度も試せます。最初に別の作業列を設けて、一連番号を振っておけば、ソートのやり直しもできます。 >540 たぶん携帯電話からの書き込みと思う。変数(Rows 1)の途中に空白があったり、Test.とか 独自処理?の部分がある。
>541の中で If Cells(tate1, yoko1).Value Like ("*A*") Then の ( )は不要です
543 :
536 :2010/10/05(火) 12:39:27
>>540 ガクブル
ちゃんとコッチでは動いてます
>>541 あわわ、仕様が昨夜の認識全然ちがくて切腹
全ておっしゃる通りです
ソース有り難うございまづ
すいませn
補正が必要なら、上から舐めてフラグ立てて、今度は下から舐めてフラグ立ってるのをどうにかすりゃ良いじゃん。 いっぺんにやろうとするから大変なんだよ。
545 :
デフォルトの名無しさん :2010/10/05(火) 22:00:03
i = 1+i として、 seru = Cells(3 + i, "B").Adress と設定。 Worksheets("sheet1").Range ("seru"), Range("seru").End(xlToRight).Copy でエラーが出ます。 まだ勉強初めて3日ですので初歩的なミスかもしれませんが、 原因の分かる人いたら教えてください・・・
何から言ってあげれば良いんだろうか・・・。 とりあえず、range("A1") 表記と cells(1,1) 表記が混在してるから、多分それじゃエラー吐く。 "seru " は変数を表しているんじゃなくて、seru って文字列を表してるから当然エラーになる。 range(range("A1)"),range("B2")) のようにカッコで括らないと認識しない。 色々とやり方はあるけど、一例として挙げておくよ。 set seru = worksheets("sheet1").cells(3+i,2) seru.end(xltoright).copy
547 :
546 :2010/10/05(火) 22:16:40
ごめん。確認したら cells(1,"C").select でも問題なく認識した。 私の間違いです。
548 :
デフォルトの名無しさん :2010/10/05(火) 22:36:49
>>546 ありがとうございます。
一応seruは、
Dim seru As Range
としてから使っているのですが、()の括りがおかしかったのでしょうかね・・
例をお借りしてもう一度試してみます。
>>548 range型変数にはsetしてあげないとダメ。
550 :
デフォルトの名無しさん :2010/10/05(火) 23:14:54
Dim sokutei As String Dim i As Long Dim seru Do While ActiveCell.Value = "" i = 1 + i sokutei = Cells(3 + i, "B").Value Set seru = Worksheets("シート1").Cells(3 + i, "B") If sokutei = "あ" Then seru.End(xlToRight).Copy Worksheets("シート2").Paste Range("B7").Offset(1).End(xlDown) Worksheets("シート5").Paste Range("B7").Offset(1).End(xlDown) Application.CutCopyMode = False ElseIf sokutei = "い" Then sokuteiseru.End(xlToRight).Copy Worksheets("シート1").Paste Range("B7").Offset(1).End(xlDown) Worksheets("シート9").Paste Range("B7").Offset(1).End(xlDown) Application.CutCopyMode = False こんな感じにElseIfが8回、Elseが1回でLoopで終了するのですが、うまくいきません・・・ シートがたくさん出てくる場合はFor Eachをどうにか組み込まないと無理なんでしょうか?
551 :
デフォルトの名無しさん :2010/10/05(火) 23:16:06
↑ 上のsokuteiseruはseruのことです。 修正忘れました。
>545,550 sokutei の値 が "あ" : "シート2" と "シート5" "い" : "シート1" と "シート9" "う" : "シートn" と "シートm" ・・・・ というのが8~9個あるってことでしょ? シート名(文字列)の変数を2個準備して sh_nm1 と sh_nm2 など Do Select Case sokutei Case "あ" sh_nm1 = "シート2" sh_nm2 = "シート5" Case "い" sh_nm1 = "シート1" sh_nm2 = "シート9" ・・・ ここに残りを入れ込む Case Else 上記のいずれにも該当しなかった処理 Exit Do End Select ここは 上記のいずれにも該当しなかった 場合はスキップします seru.End(xlToRight).Copy Worksheets(sh_nm1).Paste Range("B7").Offset(1).End(xlDown) Worksheets(sh_nm2).Paste Range("B7").Offset(1).End(xlDown) Loop Until 1 1回しか実行しないループです こんな感じで処理をまとめることができます
553 :
デフォルトの名無しさん :2010/10/06(水) 08:52:01
ユーザーフォームを出しながらシートもアクティブにしたいのですが、 どのようにすればよいのでしょうか
>>553 UserForm1.Show vbModeless
リロードは大事だね
557 :
デフォルトの名無しさん :2010/10/06(水) 13:20:51
>>554-555 ありがとうございます、できました。
ですがいくつか疑問が出てきました。
・プロパティのshowmodal=falseとはどう違うのでしょうか?
・
Private Sub UserForm_Click()
UserForm1.showmodal = False
End Sub
のように実行中にプロパティの変更が出来ないものをなんというのでしょうか
>>557 1)元は同じ値です。フォームの状態には「モーダルかモードレスか」の2種類が必ずあり、
どうせ2択だからという事でそのプロパティは「vbModalかどうか」の結果をBoolean型で返します。
元の値は呼び出した時点で確定しており、閉じるまで変化出来ない(し変化させる意味もない)ものなので
このプロパティへの代入は不可になってます。(変えたい時は一旦閉じて別の値でShowを呼び直します)
2)「参照のみ可能なプロパティ」「代入不可のプロパティ」「リードオンリープロパティ」とか、色々。
マイクロソフトもその時々で好き勝手呼んでるような気がするし、
なんか統一的な技術用語あったっけ?
559 :
デフォルトの名無しさん :2010/10/06(水) 18:08:06
>>558 ありがとうございました。いろいろあるのですね
for i = 1 to 5 'フォームをループして処理したい checkbox & i .valur = true next みたいな感じで、コントロール名の数字をループさせたいです。 確か可能だったと思うのですが、どの様に表記すれば宜しいでしょうか。 お願いします。
×'フォームを ○'コントロールを
>>560 For i = 1 To 5
Controls("CheckBox" & i).Value = True
Next
563 :
デフォルトの名無しさん :2010/10/06(水) 22:41:30
txtファイルをエクセルで開いて、同名のCSVファイルで 保存したいのです。 教えてください。よろしくお願いします。
>563 拡張子の書き換えだけじゃだめなの?
565 :
563 :2010/10/06(水) 22:54:00
すみません、補足です。 現在はテキストファイルをエクセルで開いた状態です。 最後の保存方法がわかりません。 よろしくお願いします。
566 :
563 :2010/10/06(水) 22:56:11
564さん 拡張子の書き換えのマクロを 教えていただけませんか。
>>566 マクロじゃない
「名前を付けて保存」からファイルの形式をcsvにする
568 :
563 :2010/10/06(水) 23:17:43
マクロを使うほどのことでもないかとは思いますが、 処理すべきファイル数が多いので、質問した次第です。 どうもありがとうございます。
>>568 それならコマンドプロンプトだな
ren *.txt *.csv
これだけでファイルが何万個あってもいっぺんに変更できる
Excelの話題じゃないから、これ以上はくだ質スレででも聞いてくれ
570 :
563 :2010/10/06(水) 23:42:37
569さん どうもありがとうございました。
>>568 単にこれ↓をマクロ記録すればサンプルコードが出来上がるんじゃないの?
>「名前を付けて保存」からファイルの形式をcsvにする
試した? といいつつ俺は試さずに言ってるけど。
>>562 ありがとうございます!
controlsコレクションでしたか。これですっきりとしたコーディングが出来そうです。
thx
573 :
デフォルトの名無しさん :2010/10/07(木) 13:41:44
マクロでメーラーを起動する場合、複数アドレスを指定するには どうすれば良いのでしょうか。 Excelにボタンを設置し、それを押すとメーラーが立ちあがり 自分自身を添付したメールを送るようにマクロを組みました。 ------------------------------------------------------------ Application.Dialogs(xlDialogSendMail).Show arg1:="パパ<papa@papa.com>", _ arg2:=sDate & "_今日のわんこ", _ arg3:=False ------------------------------------------------------------ Excelのボタンを押すと、上の記述を元に TO:パパ<papa@papa.com> 件名:2010/08/20_今日のわんこ と自動入力されるわけです。 今回、もう一人にも送信される様に ------------------------------------------------------------ (略)Mail).Show arg1:="パパ<papa@papa.com>,ママ<mama@mama.com", _ ------------------------------------------------------------ と追記したのですが、メーラーを立ち上げると最初の宛先しか出てきません。 宛名の見出し?を削って ------------------------------------------------------------ (略)Mail).Show arg1:="papa@papa.com,mama@mama.com", _ ------------------------------------------------------------ とアドレスだけ書けば両方出てきますが、できれば"パパ"や"ママ"の表記を 使いたいのです。 どなたか良い解消法があれば教えて下さい。
>今回、もう一人にも送信される様に >------------------------------------------------------------ >(略)Mail).Show arg1:="パパ<papa@papa.com>,ママ<mama@mama.com", _ >------------------------------------------------------------ 最後に括弧が抜けてましたが記載ミスです 今回、もう一人にも送信される様に ------------------------------------------------------------ (略)Mail).Show arg1:="パパ<papa@papa.com>,ママ<mama@mama.com>", _ ------------------------------------------------------------
うわ、今確認したら (略)Mail).Show arg1:="papa@papa.com,mama@mama.com", _ は、自分のメーラーでは送れたけどOutlookだと送れない… 困ったぞう…
576 :
デフォルトの名無しさん :2010/10/07(木) 14:30:47
Outlookだとカンマやセミコロンで区切っただけじゃだめなのね… × papa@papa.com, mama@mama.com × papa@papa.com; mama@mama.com × papa@papa.com; mama@mama.com; ○ パパ<papa@papa.com>,ママ<mama@mama.com> ○ パパ<papa@papa.com>;ママ<mama@mama.com> ○ パパ<papa@papa.com>;ママ<mama@mama.com>; なので、どうにかしてarg1でパパ<papa@papa.com>,ママ<mama@mama.com>を 記述したいです…お願いします。
>>573-576 メーラーによって受け取れる形式が異なるので、
相手のメーラーがなんであるか限定しない限り精密な制御は出来ないっす。
所詮はExcelがメーラーの実行ファイルに対し
引数として任意のフォーマットでデータを与えているに過ぎないので、
各メーラー側の引数の受け取り方や解釈の仕方や性能に依存します。
特にOutLookはかなり自由奔放でわがままなメーラーです。
こうでなくちゃいけない、そんな記述法は許さないなど、
ほかの多くのメーラーに比べても引数を受けた時の挙動が明らかに異なります。
いずれせよ、メーラーを特定できないxlDialogSendMailでは完璧な制御は不可能です。
うう…そうですね… 自分のメーラーだといけるんですが… はぁ…こんなところで頓挫なんて。 Outlookなんか使ってる奴はうんこですよ。 ありがとうございました。
>>578 もう座礁?w
その気ならまだ手は残されてますよ。
たとえばIEやFireFoxなどのブラウザはOS(のレジストリ)から
標準に設定されているメーラーのパス(新規メール作成用の引数を含む)を取得し、
この実行パスの引数(スイッチ)にFromやTo、添付ファイルなどを追記して呼び出しています。
これと同じ事をしてやればいいんじゃないでしょうか?
各メーラーでの「新規メール作成」の引数の書き方と受け取れる形は調べればわかりますし。
> Outlookなんか使ってる奴は~
RFCや経緯を知らずに言ってるならあなたも同類ですよ。
580 :
563 :2010/10/08(金) 00:52:43
571さんありがとうございました。 ファイル名がそれぞれ違うため、 CSV形式での同名保存で悩んでいた ところです。
582 :
563 :2010/10/08(金) 23:13:47
ごめんなさい。 まだ解決していません。
それだけじゃわかんねーよw
>582 >569さんの方法じゃだめなの? エクセルで開いて、なにか編集してからcsv形式で保存する必要があるの? それとも、txtの拡張子のファイルを残したまま、csv形式のファイルにコピーしたいということ?(最終的にファイルの数は倍になる)
>>580 上でどう見ても解決済みだと思ってたんだが、まだなのかよw
で、なにが解決してないんだ? どうしたいんだ?
csv保存を単にマクロ記録したらこんなのが出来た
Sub Macro1()
ActiveWorkbook.SaveAs Filename:="D:\Documents2\Book1.csv", _
FileFormat:=xlCSV, CreateBackup:=False
End Sub
ファイル名を変えたいなら、その部分を書き換えればいいだけだろ?
複数開いてるなら、ループすればいいし
面倒臭いから以下サンプル。
「個人用マクロブック」の標準モジュールに記述して実行。
開いているすべてのワークブックについて拡張子csvで元の場所に保存するマクロ。
保存後自動で閉じたいなら「Target.Close False」を追記。
Sub SaveAllToCSV()
Dim Target As Workbook
Dim SaveName As String
For Each Target In Workbooks
SaveName = Replace(Target.FullName, Target.Path & "\", "")
SaveName = Mid(SaveName, 1, InStrRev(SaveName, ".") - 1) & ".csv"
SaveName = Target.Path & "\" & SaveName
Target.SaveAs Filename:=SaveName, FileFormat:=xlCSV, CreateBackup:=False
Next
End Sub
「ファイルはすでに開いている」という前提だったよな?
だから複数ファイルを開く説明はしない。
元のテキストファイルがタブ区切りでデータの中にコンマを含んでるとかだと一手間増えるよな リネームだけじゃ対応できん ていうか質問者は情報を出さなすぎ これで答えろってのが無茶
hoge1 ~ hoge10 までの変数があります。 long型で数値を格納してあるのですが、何とか変数の数字をループさせて処理する事は出来ないでしょうか。 for i = 1 to 10 sm = sm + "hoge" & i next みたいなイメージなのですが、何か方法はありますか? 無理でしたら無理と教えてくださいませ。 よろしくお願いします。
588 :
563 :2010/10/09(土) 23:08:10
説明下手ですみません。 例えばaaa.csvの拡張子を手動でtxtに変え、エクセルで開いて編集した後、 aaa.csvで保存したいのです。bbb.csvなら最後はbbb.csvで。元のファイル が消えても残ってもそれは構いません。 csvファイルをエクセルで開いた場合、桁数の多い数値が変になってしまうの を防ぎたいため、上記のような処理を行っています。 考えてくださっている方々、どうもありがとうございます。
589 :
デフォルトの名無しさん :2010/10/09(土) 23:37:01
>>587 そういうことがしたいときは配列を使わない?
dim hoge(10) as long
for i=lbound(hoge) to ubound(hoge)
sm = sm + hoge(i)
next
あ・・・配列使えば良かったか。 こりゃお恥ずかしい・・・。
ありがとうございました。 配列ですよね・・・本当に自分で情けなくなりました・・・。
>>563 csvをわざわざtxtにして読み込んでる理由はわかった。
それならcsvファイルをtxtとして読み出してcsvとして上書きするマクロがあればいい。
が、もし今後も同じ作業を何度も続ける予定なら、
そのcsvではなぜ値がおかしくなるのか?を理解した方がいい
その上で元々の出力の段階で事前に加工にした方が間違いがない
>>590-591 プログラミングの学習過程では誰しもそういう疑問に触れるから気にするな
むしろお前は今までの何倍も賢くなったんだ
>>563 ちゃんと動くマクロを作りたい/作って欲しいと思っているなら、
とにかくそのcsvファイルの出所と、内部の正確な仕様(記述方法)を開示しろよ
でなきゃ何度説明してもマクロ作っても無駄に終わるだろ?
そもそもcsvと言われても形式はひとつじゃないって知ってるか?
Excelは妙に賢い上にお節介だから、csvを自動で解析したりなんとか型変換しようとしてくれるが、
完全な判断はそもそも不可能だしExcelの"好み"で違う形で読み込まれる場合がある。お前がその例。
>>594 開示できない場合もあるんじゃないか。
>>563 の情報が少ないのはそのせいかもな。
察してやれよ。
なのかもな。だから黙ってたが、さすがにこのままじゃ進展がないし回答側も不毛だろう
そう察したので強めに書いた。居座り具合からしてちゃんと答えを欲しているのだろうし
開示できない部分は伏せて1、2行分コピペするだけだろ。知りたいのはフォーマットだ
それすらしない質問主にだんだん腹が立ってきてたってのもある
誰もcsvの中身や出所なんか興味ないし知りたいとも思ってない
質問主の
>>588 、断っておくが俺はお前に「帰れ」「回答しない」と言ってるわけじゃないんだ
「回答するため」に「前提条件をちゃんとくれ」と言っているだけだ
「前提条件」が自身で判断できないようなら、出来うる限り状況のすべての情報をくれという事だ
IQが20違うと話が通じないってこういうことなんだな
正規分布に従うとすれば68%の人間はIQ85~115の範囲にいるからな
600 :
デフォルトの名無しさん :2010/10/10(日) 15:56:05
A1から下に順番に見ていき(MAXで7000行ほどのデータ、空白行は無し) 赤文字のセルの行を最終的にまとめて削除します。 一個一個削除して言ったら時間的にもかかるため、 行選択をif文でひっかかった行を選択してしてまとめて削除したい処理なんですが dim DEL As String Do While Range("A1").Offset(i, 0) <> "" If Range("A1").Offset(i, 0).Characters.Font.ColorIndex = 3 Then DEL = DEL & i & ":" & i & "," End If Loop DEL = DEL &"10000:10000" Range(DEL).Select Selection.Delete これだとどうしても 「rangeメソッドは失敗しました _globalオブジェクト」 と出ます 変数はStringで格納されているし 仮に変数をCStrに変換しても同じです ちなみに変数に格納されている「"1:1、5:5~"」をじか書きに直してそのまま実行すればうまく削除されてます 何が悪いのか教えてください
601 :
デフォルトの名無しさん :2010/10/10(日) 15:59:41
DELの文字列が長いんじゃない? たしか長さ制限があったはず
602 :
デフォルトの名無しさん :2010/10/10(日) 16:06:01
>>601 すいません
DELの中身を下記みたいに15文字してもにしても変わりませんでした。
"1:1、9:9、10:10"
要は
Range("1:1、~").SelectはいくらでもOK(1000文字ぐらいまでは確認済み)で
Range(DEL).Selectはだと5文字でもダメです
DEL = "1:1、9:9、10:10" Range(DEL).Select Selection.Delete で試したら動いたから、DELの中身が予期せぬ値な気がする
604 :
デフォルトの名無しさん :2010/10/10(日) 19:06:54
プログラムの独学者なんで基本的な事を伺わせてください。 構造化プログラミングの原則には、プログラムは順次、反復、分岐のプロセスのみで作成すべし、のような格言があると聞きます。 一方VBAにはまずマクロの記録機能があるため、順次で処理していく場合は多くはそれで自動記述できてしまう。 なのでVBの制御文を書くべき部分とは、まず反復(Do While、Do Until)や分岐(If~End)が主になるのではないか、とVBAについて自分なりに考えています。 (分岐にはIf関数も使えるでしょうが、それをファイル上のセルに準備するのはどこまで現実的なものか判りかねます。) 他にはコマンドライン引数的に値を渡したい時のInboxも書くしかない部分とも思います。 上のような認識、あってるでしょうか?Excel上での計算業務に限定することとしてですが。
マクロの記録機能ってなんですか? そんなのプログラマの記憶の中には 存在していません。 聞かれても分かりません。
>>600 Rangeの引数のアドレスには255文字までの制限があるんだよ。
だからといってUnionなんか使っちゃだめだから、作業列にフラグを立ててソートして削除するとか
フィルタオプションで抽出しろ。
フィルタオプションは確か書式も引き継いで抽出する筈だ。
>>604 そんな格言なんて聞いた事ないし、相当古い考え方で認識しようとしてるんですね
「構造化プログラミング」も近年聞いた覚えがない
VBAに限らず、現在一般的なプログラミング言語はほぼ例外なくすでに構造化されている(VBA、VB6、VB.NET、C、C++、C#、Java、JavaScript等もそう)
「真に構造化されていないプログラミング」が書けるのはいまやマシン言語とかの超低級言語だけじゃないかと思うので
あなたは相当昔の考え方のままVBAに取り組もうとしてるんじゃないかと思う
「一方VBAには」と始まっているが、前述の通りVBAは構造化プログラミングだと思う
むしろC言語で言うところの「Sub main」という開始点すら隠蔽されており、
すべてのコードはブロック化されているし、それらがどこかから呼び出される形になる
EXCELに付いてるマクロの記録機能は、たしかに「順次」処理のコードしか作成できない
でもプログラマー脳なユーザーからするとそれは単なるサンプルコードでしかない
それを叩き台にしてコードを加筆・修正する段階で「順次反復分岐」は必然的に生まれるに過ぎない
あくまでEXCELという単位で考えた場合、その存在そのものが構造化プログラミングでしょ
>>604 何考えてるのかよくわからない
「EXCEL」という世界でのVBAの位置付けを知りたいのか?
EXCELは基本的にはワークシート上で完結出来るならそうすべきものだ。(あくまで基本的に。VBAが好みなら使えばいい)
だがワークシート式やUI上の機能にはいくつかの制約がある。
まずワークシート式は1行しか書けないという制約があり、長い式が書きにくく人間の感覚的限界があるし、
そもそもワークシート式で使える演算や関数の結果は1つの値(ないしは1つの配列)しか返せないし、
最終的に結果を返すのは必ずその式が書かれたセルに対してであり、他のセルに代入することは出来ないし、
値以外を操作すること(セルの色やフォントといったセルの書式を変化させること等)も出来ないなど。
またEXCELが用意している各種機能(ソートするとかオートフィルの制御など)にも前提条件があり、それを逸脱する場合は使えない
ワークシート式にしても各種GUIの機能にしても、それらに与えられている制限は
主にライトユーズでの使いやすさを上げるために存在するか、あるいはUIの仕様に配慮した結果生まれている
VBAはそれらを補完する、あるいは置換するという立場にある。
VBAを使えば上記のような制約からほぼ解き放たれるし、逆にその制約を再現することも、より制限を加える事も出来る。
つまりEXCELで出来ることはすべて再現できるし、それ以上のことも出来る。
さらに言えばWindows上で出来る事はほぼ実現できるわけで、1ソフトのマクロ言語としては少々パワフル過ぎる側面がある。
そのため、VBAを利用するユーザー側にもかなり高度なプログラミング知識を要する。
609 :
デフォルトの名無しさん :2010/10/10(日) 22:41:24
私は初心者です、質問があるのですが 次のようなことは出来るのでしょうか セルf3に下の数値が入るとします 1~100000 この時 100と表示させたい 100001~200000 の時 200と表示させたい 200001~300000 の時 300と表示させたい 300001~500000 の時 500と表示させたい すべてセルG3に表示させたいです。
>>609 可能です。ワークシートの式で実現するなら例えばIF関数かRANK関数でどうぞ。
VBAなら普通はIF文を使うか、Select文を使って下さい。
>>604 > 構造化プログラミングの原則には、プログラムは順次、反復、分岐のプロセスのみで作成すべし、のような格言がある
格言というか、定義です。
「プログラムは順次、反復、分岐のプロセスのみで作成【出来る】」のが構造化プログラミングです。
逸脱するものは構造化プログラミングではない、という。
それに、「原則的にプログラムは構造化プログラミングで作成すべし」が正解です。
これは言語レベルの話ではないので、VBAであっても非構造化コーディングも出来ます。
>>607 さんの例に出てくる言語はいずれも構造化プログラミングを標準でサポートしており、
準拠するコードを書きやすいよう配慮されているという点は正しいですが、必ず準拠するいうわけではないです。
例えば、乱数を返すrnd関数と、Randomize関数は引数なしに内部的に影響を及ぼす関連があります。
またDate関数やNow関数などのように引数はないがシステムの時間に依存して結果が変化します。
もっと単純な部分でも、グローバル関数を利用して結果が変化するようなコーディングがあります。
これらは関数単位で見た場合、すべて非構造化であるとも言えます。
このような実装は構造化プログラミングに違反する事になりますが、実用レベルではそれが最善の場合もあります。
よって何が何でも構造化に準拠すべき、というわけではないと考えています。「原則的に」という例外はここの事ですね。
なお上記を関数単位ではなく全体としてみた場合、結果の一意性の法則は保たれているため構造化である、という事もできます。
612 :
611 :2010/10/10(日) 23:38:36
>>661 の続きです
この構造化プログラミングという考え方の主な目的は、
コードの見通しを良くし保守可能な状態を常に保つことです。
簡単な例で言うと「ラベルジャンプを複雑に多用するような分かりにくいコードを書くな」という話で、
結局はわかりやすくコーディングするための指標でしかないわけです。
とどのつまり、
>>604 が考えてらっしゃる事がなんなのかわかりません。
理解していない用語に踊らされているだけなのかもしれません。
ワークシートの式とVBA、どちらにコーディングすべきか?という命題の
絶対的な指標を求めているのなら、
>>608 さんの話が近いんでしょう。
EXCELのセルは、VBAから見えるとグローバル変数と同等であると考えることが出来ます。
そうすると、引数に依存せず特定のセル値によって結果が左右される処理は
すべて構造化プログラミングではない事になります。
この例外を許さないのであれば、コーディングはほぼ不可能になります。
ある程度例外を許さなければ話にならないでしょう。
結局は例外のために見通しがどの程度悪くなるかと、
例外のおかげでどれだけの恩恵があるか、この両者を天秤にかける必要があります。
またその裁量が正しかったかどうかは未来では流動的です。
結局正しい答えはこれだというのはなく場合によりけりになります。
しかも保守する方の力量(VBAの理解度)も含めると、答えは一意になり得ません。
613 :
デフォルトの名無しさん :2010/10/10(日) 23:54:07
XP + EXCEL2000 ワークシートに図形(複数)を配し、グループ化して それぞれを"waku", "frame", "sf1","sf2","elmnum","nodnum" と名付けました。 UserFormのチェックボックスのCaptionにその名を使用して、 図形の見え隠れをコントロールしようと下記のコマンドを実行しました。 "elmnum"のところで止まり Run-time error '-2147024809(80070057)' The item with the specified name wasn't found. と出ます。 モデュールで Worksheets(1).Shapes("elmnum").Visible = False を実行すると動くので、下記の①、②のmyCtrl.Captionの 両側に「"」が付けられれば動くのではと考えるのですが その方法がわかりません。アドバイス願います。 Private Sub CommandButton1_Click() Dim myCtrl As Control For Each myCtrl In Me.Controls If TypeName(myCtrl) = "CheckBox" Then If myCtrl.Value = False Then Worksheets(1).Shapes(myCtrl.Caption).Visible = False ・・① Else Worksheets(1).Shapes(myCtrl.Caption).Visible = True ・・② End If End If Next End Sub
>>613 その名前はない、というエラーでしょう?
単にチェックボックスコントロールのCaptionの文字列を打ち間違えてるんじゃないの?
①と②それぞれの前にDebug.Print myCtrl.Caption を入れて、
エラー直前になんという名前で呼び出しているか調べてみてください
610>> …RANK関数? 統計で使えるとしたらクラス分けだと思うが…勘違いか?(さらにクラス分けを行う関数はEXCELに用意されてない) 出来るならやり方を知りたい、面白そうだから。
>>609 VBAではないが、VLOOKUP関数で割と簡単に実現可能。
VLOOKUPの検索の型にTRUEを指定すると、範囲区切りで
表を検索してくれる。
セルH1から下方向に以下のデータをセット
1
100001
200001
300001
500001
セルI1から下方向に以下のデータをセット
100
200
300
500
OVER!
セルG3に以下の関数をセット
=VLOOKUP(F3,H1:I5,2,TRUE)
以上
>>616 VLOOKUPが分りやすいが=LOOKUP(F3,H1:I5)とも書けるな。
618 :
デフォルトの名無しさん :2010/10/11(月) 08:27:56
609です 皆様、いろいろアドバイス有難うございました なんとか表示させる事ができました。
>>563 まだここ見てる?
TXTでもCSVでもEXCELで開くと
シート名=ファイル名になってるよね。
シート名をファイル名に使ってCSV保存するように
組めばお望みの結果になるんじゃない?
後は、マクロの記録でやるなり、ネットで
調べるなりしてね。
620 :
517 :2010/10/11(月) 19:22:32
>>520-522 お礼とお返事が遅くなり申し訳ございませんm(__)m
とても助かりました(´;ω;`)
ちなみに先生からは何も言われませんでした…
課題丸写しの学生なんて昔からいたもんな ここ見ててそのまま提出したやつが他にいてもおかしくない
622 :
613 :2010/10/11(月) 20:49:13
>>614 アドバイス有難うございます。
613の例に即していうと "sf3"という今回の図形で使用していないチェック
ボックスを配置していたためにエラーが起きていました。
改良策として、フォルムのチェックボックスのEnabledをすべて
Falseとしておき、for each ループでShape.Nameをとり、その名前の
チェックボックスのEnabledをTrueとして、図形内にない名前を回避しようと
考えました。
ただ手動で終了させないと抜けられない。
With Worksheets(1)
For Each myShp In .Shapes
For Each myCtrl In Me.Controls
If myCtrl.Name = myShp.Name Then myCtrl.Enabled = True
Next
Next
For Each myCtrl In Me.Controls
If TypeName(myCtrl) = "CheckBox" Then
If myCtrl.Enabled = True Then
If myCtrl.Value = False Then
.Shapes(myCtrl.Caption).Visible = False
End If
End If
End If
Next
End With
623 :
デフォルトの名無しさん :2010/10/11(月) 21:08:13
604です。辛口のコメントを多くのみなさんからいただきましたが、それはそれとしてカキコに大変感謝しています。 特に611さんのコメントは勉強になりました。プログラミングは結局、原則を重視しても例外は常にある、ということで一慨に3通りの操作でプログラムの内容を決めつけるのは無理ということのようですね。 実のところ、私はExcel操作上でマクロの記録機能が使えずにVBで記述するべきものが何かを整理したかっただけでした。そこで順次、反復、分岐の3操作を持ち出してみたのですが、これらだけでは話は終わらないということですね。
すごく簡単なことなのですが If Worksheets("Sheet2").Range("C6") = Worksheets("Sheet2").Range("C7") Then msgbox A else msgbox B end if これでシート2のC6とC7の値が等しいときにmsgboxAを表示できるはずなのですが表示されません どうすればいいでしょうか
C6とC7等しくてもmsgboxBが表示されます
>>624 普通に考えて、セルに入っているデータが違うから
Bが表示されるんだと思うよ。
各セルには何が入ってんの?
同じ数字だよ 関数は使わずVBAで代入してるから大丈夫なはずなんだけど
>>624 本当に等しいかどうか、よく確認して下さい
セルに余分な空白が入っていたりしませんか?
>>627 そのIf文の直前にこれ足して確認してみ
Debug.Print ">"; Worksheets("Sheet2").Range("C6"); "<"
Debug.Print ">"; Worksheets("Sheet2").Range("C7"); "<"
>>627 そのデータを代入している部分の
VBAコードを晒してみて欲しい。
631 :
デフォルトの名無しさん :2010/10/11(月) 22:58:31
>大丈夫なはずなんだけど この思い込みでどれだけ回り道をしたことか w
>>628 問題ない
>>629 だめだった
>>630 Worksheets("Sheet2").Range("C6").Value = Worksheets("Sheet1").Range("B8")
Worksheets("Sheet2").Range("C7").Value = Worksheets("Sheet2").Range("D1")
>>631 今回は本当に何がいけないかわからない
.Valueが付いてないから?
1行目の右側がSheet1になってるのは間違いではないんだな
>>632 いやいやいや、
>>629 は何かというと、本当にデータが同じかどうか
自分の目で確認しろって言ってんの。それで結果が変わるわけじゃない
Excelのバージョンは何?
あと、そのコードじゃC6とC7の値が同じって説明にはなってないよ
>>632 ううむ、そのコードだと、やはり
データの参照元であるB8とD1に
違うデータが入っているとしか言いようがないな。
=if(C6=C7,"OK","NG")という関数を
sheet2のどこか空いたセルに入れてみて
結果はどうなるかな?
これでOKが出るなら、ちょっとわからないね。
>>624 数値の計算誤差だろ?
中身は足し算や引き算した時刻なんじゃないの?
同じに見えても微小誤差で違うことはよくあること。
その場合、
>>636 の=if(C6=C7,"OK","NG")では本当の違いは検出できない。
=IF(C6-C7=0,"OK","NG")としないと駄目だ。
>>637 が外しなら、どちらかの表示形式が文字列で、数値と文字列で比較してるってことも考えられるわな。
もしくは、表示桁数を制限しているために、表示桁数に合わせるための四捨五入前の元の値が違うとか?
cstrで文字列に変換してから比較したら?
>>637 できました!!!
微妙に誤差があったみたいでした
みなさん本当にありがとうございました
642 :
デフォルトの名無しさん :2010/10/12(火) 20:12:10
Ramge(A1).value = "あ" Ramge(A2).value = "い" Ramge(A3).value = "う" … こういうのが延々と続く処理があるのですがこれを一行で書く事は可能でしょうか? たとえば Ramge(A1:Z1).value = "あ、い、う…" みたいな感じで 当然上記は全列に同じ文字列が入ってしまうのでダメですが
配列に突っ込んでからスプレッドシートに展開すれば行ける。
>>642 Range("A1:A3") = Application.Transpose(Split("あ,い,う", ","))
大量の定数はVBAのソースにそのまま並べて書くんじゃなくて、最初からワークシートに入れておくべき ワークシートから配列への代入とか一発でできるから
たとえばそのマクロが実行されたPCでパスは問わず book.xlsというファイルが開かれているか確認したいのですが たとえば C:\book.xls C:\aaa\book.xls でもとにかく、どこのパスのbook.xlsファイルが開かれていてもダメです
質問です 文字列XはA1,B,CDがカンマ区切りです 文字列YはCD,E,FA,B,HG等がカンマ区切りで入っています カンマ区切りですが両者共にstring型です 文字列Xの各値と文字列Yの各値を比較して順番は違ってても値が同じならTrue判定したいです また、文字列YはランダムでXは固定です 個数が多くてもXの値が全てYにあればTrueとします どなたかヒントを Xのカンマ数でカウンターまわしてカンマでデリムして比較とかですかね
>>646 For Each w In Workbooks
If w.Name = "book.xls" Then MsgBox "ダメ"
Next
>>647 SplitしてソートしてJoinして文字列の比較とか
いくらでも方法はある
webクエリでデータ取り込み時ページ自体が存在しないと 404エラーでデバッグのダイアログが出て中断してしまうのですが たとえばこのエラー情報をキャッチして例外処理に回すなどで ダイアログを出さずvbaの動作を中断せずに済む方法はありますか?
>>650 ページが存在するかどうか調べる方法は色々ある
比較的手軽でよく使われるのがMSXMLオブジェクトを使う方法
ただしネット上の日本語ページのサンプルは粗悪な参考書の孫引きばかりなので英語サイトを見ること
652 :
647 :2010/10/12(火) 23:55:25
>>649 jointしたいのは山々なんですが文字列Yの値が個数も値もユニークな為
文字列Xと同じ文字列(配列)にできないです
できなければ、Falseって事?
>>651 レスありがとうございます
MSXMLオブジェクトについて調べてみます
>>652 内容が完全に同じかどうか調べるんなら、要素の数が違ってた時点で同じじゃないわな
素早く結果が欲しいなら、最初にLength調べれば最低限のチェックになる
次にSplitして要素数をチェック、ここまで一致してたら、あとは1個ずつチェックするしかない
>>652 649じゃないが、彼の補足。
両者ともに、Split関数で動的配列に変換して、内部を何らかのアルゴリズムでソートする
それぞれソートした結果をJoin関数でつなぎ、1つの文字列に戻す
両者のカンマ区切りの要素が同じであれば、ソートして再連結した文字列も必ず一致する
この文字列同士を比較する事で一致か不一致かがわかる
X列とY列の部分で、どのように比較するのかによってこれが有効かどうかが決まる
X1とY1、X2とY2など隣どおしのものだけ比較するなら、
>>654 の「最後は1つずつチェック」が有効
X1とY1、X1とY2、X1とYn・・・XnとY1・・・XnとYn、とすべての組み合わせに対して比較が必要なら、
数が多ければ多いほどソートを用いるほうが高速に処理できる
656 :
655 :2010/10/13(水) 07:22:45
「値が同じならTrue」なんて言うから↓を見落としていた。
> 個数が多くてもXの値が全てYにあればTrueとします
Xが"A1,B,CD"、Yが"CD,E,FA,B,HG,A1"のときはTrueと判定するという事か。
なら
>>654 が妥当なんじゃないか?
集合論的なうまいアルゴリズムがあるならそれが最良だろうけど。
>>654 補足。
最初に=で文字列の完全一致を調べる。(一致なら総当りで調べるまでもなくTrue)
Len関数を比較するのは無意味。(不一致ならFalse確定としたいが、要素数の不一致でもTrueになる可能性があるため)
同様にSplit関数の要素数を比較するのも無意味。(同理由)
以後、Xの全要素についてYに含まれているか総当り。(Xの全要素が見つかった段階でループ終了してTrue、ループ終了段階まで見つからなければFalse)
658 :
647 :2010/10/13(水) 08:01:22
>>656 Trueです
thx
>>657 有り難う
総当たりでパフォーマンス悪かったら集合論アルゴリズム考えるわ
>>658 XとY、それぞれについて
保有する要素に重複はりあり得るの?
ないのなら、コレクションオブジェクトにYの要素を
ぶち込んで、そこからXを一つずつ削除していって、
エラー発生の有無でYに含まれない
Xの要素があるかどうかを判断するやり方が使える。
これならソートする必要もない。
質問です。 Excel2003なんですが最近急に保存すると同名の.tmpファイルが 作成されるようになったんですがこれって何でしょう?
XとYはどのくらいの要素があるんだろ? あまりにも多いとCollectionのRemoveは遅いからねぇ。 Dictionaryも遅さは似たようなもんだ。
要素数と比較回数が多い(だいたい4桁以上)なら、データ構造から見直した方がいいかな 文字列は直感的でわかりやすいけどパフォーマンスは悪い あと、質問者の文章の書き方にイラっと来る trueとか書いてないで普通の丁寧な日本語を使え
665 :
647 :2010/10/13(水) 12:49:04
>>659 そんなスタイリッシュなやり方があるとは!
凄い!感動しました!
因みにXY共に同文字列には重複する値はありません
現状ではFOR文2つかましてXの要素をYに総当たりで実装しました
コレクションのやり方でも実装してパフォーマンスを計測します
有り難うございまづ
Colllectionを使うのは構わないが削除時のエラー発生で調べるのはよくないね。 別の判定方法があるだろ?
そのシートが完全に空白(どこのセルにも何も書かれていない)である 事をチェックしたいのですが 教えてください
>>667 セルが空白ならいいの?
結合セルとか書式の変更とか塗りつぶしとかあった場合はどう判断するの?
>>668 あー、全部だめです
新規作成した時の状態
670 :
デフォルトの名無しさん :2010/10/14(木) 03:22:47
なら新規作成した方が簡単だよ
セルの幅や高さも変わってちゃだめなの?
>>665 そもそもソートはほぼ不要だろ。要素数不一致がアリな時点で。
処理速度もこの場合飛躍的に速くなる気がしないけどなぁ。(むしろ遅くなるかもと思った)
つか高速な方法を欲しているの?
XとYに出現する値はパターンが決まってるのなら(すべての値名を把握できるのか?)
出現し得る値を予め完全に把握出来るなら速いコードも可能かもしれないが、
情報少なくて法則がわからないんで突っ込んで考える気にならないや
>>666 …Addのエラー?
それともDictionaryのExistsと勘違いしてるの?
Dictionaryって知らなくて今調べたのだけど、 Existsメソッドがあるので 今回のケースでは(お行儀的が良いという観点で) 適しているかも知れないね。 ただ、DictionaryオブジェクトってExcelの持つ機能なんだっけ? CreateObject("Scripting.Dictionary")っていう宣言の仕方は あまり見ないものだし、VBAのヘルプにも出てこない。
>>673 Officeインストールすればライブラリ入るけど、Excel固有のオブジェクトじゃないでしょ
Microsoft Scripting Runtimeライブラリのうちの独立したものだったかと
>>672 なんだよ、俺への突っ込みかよ。
別に勘違いしてないぜ。
>>659 がそのようなことを書いてるので、それは良くないと書いたまで。
おれもDictionaryのExistsが普通だと思うが、Collectionを使うならRemoveしての
エラー判定はよくないと書いたんだよ。
そもそもRemoveはCollectionにしろDictionaryにしろしょちゅうやるもんじゃない。
>>675 具体的に何がよくないの?
良くないってだけじゃなく、ちゃんと理由を述べたうえで
こうすればよいっていう前向きな方向に書いて欲しい。
対案無き批判に価値なし!
またファビョってるのか? 何がよくないかなんてRemoveがよくないって何度も書いてるだろ? col.Remove("パープリン")のエラー判定よりa = col("パープリン")のエラー判定の方が軽いんだよ。 よく分らなければDictionaryのExists覚えろ。 文字列をSplitする程度の要素数ならそっちの方が軽いし簡単だ。
>>678 > col.Remove("パープリン")のエラー判定よりa = col("パープリン")のエラー判定の方が軽いんだよ。
最初からそれを書けって言ってんのよ。
コミュニケーションの下手な人だね。
>>675 ,
>>678 672は俺だ。ツッコミというか単なる返答。「別の判定方法があるだろ? 」と意味深に書くからw
どういう意図で「よくない」と言っているのかと思ってね。(エラー生成は悪だとかスタンスによっても色々な「良くない」があるから)
「遅いからよくない」って言ってるわけだ。エラー見るならItemで参照するのが一番速いと。
よくわかった、ありがと。
>>673 ,
>>674 参照設定しとけばCollectionと同じように使える。兄弟(先代?)のVB6でもそう。
たしかIE5.5以上またはOfficeが入っているWindows環境なら利用可能なので気軽に使ってOK。
DicとColはよく似てるけど、Dicにはいろいろと面白い機能があるので場合によっては便利な時がある。
(Existsでキーの有無を判定できる、Keysで登録中のキー一覧の配列を取得出来るなど)
ただ特性がやや違うためCol使ってたものを単にDicへ置き換えるとバグ起きやすいから注意。Itemへのアクセス速度的にはややColが優位。
(Colは実はKeyとしてObjectも入る(!)がDicはStringのみ、DicのItemはKeyなしに出来ない、Add時のItemとKeyの指定順が逆など)
681 :
665 :2010/10/14(木) 22:21:43
>>672 ソートはしてないです
規則性は全くない訳ではないので、総当たり処理の前に簡易比較してます
コレクションのが若干遅いようです
682 :
デフォルトの名無しさん :2010/10/15(金) 00:27:43
すいません。初心者です。 処理速度(比較回数?)で質問なんですが、 If a = b Then Else MsgBox "test"; End If と If a <> b Then MsgBox "test"; End If では 処理速度かわりますでしょうか?
お前の人生で、その速度は重要なことか考えよう。
684 :
デフォルトの名無しさん :2010/10/15(金) 00:33:02
682です。説明不足でした、すいません。 これだけだと、仮に処理速度が違ったとしても、 微々たるものだとは思うんですが、数万回実行することを想定してまして 質問させていただきました。
想定はしなくていい 実験すればいい
1Ghz = 1秒で1,000,000,000(10億)クロック 今は1クロックで何命令実行できるんだっけ? パイプラインとかあるからよく分からん。
>>684 たぶん数万回では差はでないよ
それぐらい単純な演算だと今のパソコンは数千万~数億回の処理でやっと違いに気付く程度
それよりもプログラムは保守性や可読性を考えて素直に書くべき
それによって節約できる時間の方がずっと大きい
つまり後者を使え
>>686 平均すると1クロックで3命令ぐらい実行してる
データシート見ると0.33クロックとか書いてある
689 :
デフォルトの名無しさん :2010/10/15(金) 01:00:21
>>688 すげーな。
昔は1命令実行するのに最低で1クロック
長い命令だと、数クロックかかったものだが、
いまや1クロックで3命令なんだもんな。
そもそも、その程度の処理速度気にするなら最初からVBAでやる時点でダメだろ 何だかんだネイティブコードには勝てないんだから
>>681 XとYの元のセル内容(文字列内)は書き換えたらいかんの?
もし良いなら2回目以降の判定処理を劇的に高速化させることは可能だけど。
(Xが"A,B,F"でYが"A,CD,B,F"のとき→Yを"A,B,F,CD"と書き換えても良い)なら
XのLength分だけYを抜き出して比較するか、InstrでY中のXを探すことで一致する場合は1回の処理で確定出来る。
(判定を1回しかやらないのなら書き換えてもあまり意味はない)
>>682 1ステップ増えてるんだから当然変わるけどほとんど変わらない。(微分みたいな存在だな)
この場合重要なのはコードの読みやすさのほうだろね
前者の場合「コード書き忘れてるのか」と勘違いしそうだ('処理なし などコメントがあればいいけど)
ちなみに関係ないがDebug.Printはコンパイル後でも残っているので呼び出し回数が多いと
実行速度にわずかだが影響を及ぼす。これは空のIf文より重いと思う。
速度気にする場合はコンパイル時にコメントアウトするといいよ
693 :
デフォルトの名無しさん :2010/10/15(金) 08:24:11
VBAの処理速ででクロックってあんた・・・
最近VBA勉強始めたんですけど、ActiveXコントロールをワークシートに配置して作ってたんですが ユーザーフォームというのがあることを知りボタンなどを移植したいんです ワークシートからユーザーフォームへのボタンとかの切り取り貼り付けって出来ますか? それとも別に作り直さないといけませんか?
695 :
デフォルトの名無しさん :2010/10/15(金) 11:18:39
作り直すっつったって、そんなに手間暇かかるもんじゃないっしょ。 ツールボックスから選んでフォームに持っていくだけじゃん。 ごちゃごちゃ考える暇があったら作り直す方に100点
作り直しに200点
>>695 ,696
やっぱり作り直しですね
ちなみにワークシート上のボタンなどを単純に削除すると自動生成されたコードが
ゴミのように残ってしまうのですが、削除手順とか特にありませんよね?
エクセルでVBAのプログラムを書いています。 数値入力のインターフェイスの設計がエクセルのセルがすでに設計されているので、 エクセルで開発しています。 セルからのデータ入力において、 for n=1 To 100 nn=1+3 'セル4行目から開始 iData(n) = Cells(nn, 2) next n 「'セル4行目から開始」 のようにプラス3を付けたしてやっています。 3行目までのセルが増えた場合、ずれます。 入力セル設計時の変更にも耐えられるコードの書き方は あるのでしょうか? 教えてください。
for n=1 To 100 nn=n+3 'セル4行目から開始 ここ変更しました。 iData(n) = Cells(nn, 2) next n
>>698 そのままで十分でしょ。
1 + 3 の部分を一文字書き換えるだけじゃん。
凝った作りにしようとすると、後任が苦労するよ。
うーん。 定石があったらなぁと思い。。 やはり開始行数の定数化が定石かなぁ
名前を付ければいけるんじゃないの? まず、特定のセルからの相対座標なら Range("B4").Cells(1,1) などと表現できる そのうえで、入力領域の座標に名前を付ければ Range("入力領域1").Cells(1,1).Value などという表現ができたような気がする 名前を付けた領域座標は行の挿入時など、Excel側で補正してくれたはず
俺も面倒だからセルに名前付けて [名前].Cells(1,1).Value = ってやっちゃうわ 別に定数でもいいんだけど、その場のノリだけで作ってる 使い捨てマクロの時は大体こうしてるよ
入力領域ですか。知りませんでした。 で、名前の付け方を・・・ とまぁ、自分で調べず聞くのもまずいので、 考えます。いったん解決です。
>>704 >>702 の入力領域ってのは対象のセルのことをなんとなくそう書いてみただけで
そういう名前の機能ではない]
ポイントはセルや範囲に名前を付けられるってことだけ
ますます、わからないっす・・・
>>706 1~3行目は何の役割を果たしているの?
そもそも入力位置が変わることが
設計としてよくないんだが。
たとえば、配列を仮に1から始めるとします。 セルを1行目から数値入力すればいいのですが、 最低でも一行目・一列目はその列の名称などが入ります。 (セルにカウントしない機能があれば別ですが) さらに、シートの表題などをかけば、また入力項目が下にさがり、 5行目からの入力開始となり、配列の数字と変わります。 もちろん、ずらせばいいのですが。
簡単な例 セルB4からB103のそれぞれのセルに1~100の数値を設定する 手順 1) セルB4に名前を付ける セルB4を選択した状態で、[挿入]-[名前]-[定義] 参照範囲を確認し、名前を付ける ここでは、名前を 処理開始点 としてみる 2) マクロを記述して、実行 For n = 1 To 100 [処理開始点].Cells(n, 1).Value = n Next n 以上 この状態で先頭に行を追加すれば、処理開始点の座標は Excel が B4=>B5 に自動的に補正してくれる 上の説明は Excel2000 のもの、最近のバージョンのメニューは知らん
かたじけない
>>708 列名称が入力開始位置の目印となる固定的なものであれば、
その列名称を検索して見つかった位置の一つ下を
入力開始位置とする手もある。
目印をいじらないよう利用者に徹底する必要があるけどな。
>>708 向けに書くと、evaluateを使わないので有れば
Range("処理開始点").Item(n).Value = n
Range("処理開始点")(n)..Value=n
等と書く
ピリオドが一つ余計についたみたいだ。
>>771 キーとシート名を渡すと、入力開始セル座標がわかるルーチンを作れですナ
みなさん、色々やってるんですね。
ユーザーフォーム1にあるイメージ1にコマンドボタン一つでシート上にある図1,2,3...と表示していきたいのですがどうすればいいでしょうか
716 :
デフォルトの名無しさん :2010/10/16(土) 20:09:02
すいません質問があるのですが セルBの1~10に入力してある文字に新たに決まった文字を追加するマクロを作りたいのです 1つのセルなら〒を追加したいだけなら With Range("b1") .Value = "〒" & .Value End With End Sub でできると思います。これをbの1~10にするにはどうすればいいいでしょうか? Dim K As Long For K = 1 To 10 With Range("bK") .Value = "〒" & .Value End With Next だと作動しません。よろしくお願いします
>>716 With Range("b" & K)
>>716 For Each R in Range("B1:B10")
R.Value = "〒" & R
Next
720 :
716 :2010/10/16(土) 20:34:26
With Range("b1:b10") .Value = Application.Text(.Cells, """〒""@") End With ほんとはあと2行書かなきゃいかんけど
一文字だから With Range("b1:b10") .Value = Application.Text(.Cells, "\〒@") End With だな。
VBSなのですが Functionの中でFunctionとかのプロシージャって使えないんですか? GOTO文みたいな使い方って意味です
意味不
vbsはスレチ wshスレ行け
VBAなのですが Functionの中でFunctionとかのプロシージャって使えないんですか? GOTO文みたいな使い方って意味です
>>726 こういうこと?
Function test() As String
test = "呼ばれました"
End Function
Function CallTest()
Dim strMsg As String
strMsg = test()
MsgBox (strMsg)
End Function
>>726 GotoをイメージしてるってことはFunctionじゃなくてSubでは
Goto(ジャンプしたらそれっきり)みたいな使い方はできない
Gosub(処理が終わったら元の流れに戻ってくる)ならSubの名前をそのまま書くだけ
ちなみにVBAにもGotoはある
推奨されないから参考書でもほぼスルーしてることが多いけど
>>726 Gotoで何をしたいのか分からないけど再帰関数じゃダメなの?
> GOTO文みたいな使い方って意味です この文の意味がわからん
Function test() As String test = test2() End Function Function test2() Dim strMsg As String strMsg = "hoge" test2 = strMsg End Function Msgbox test() みたいな、要はFunctionを入れ子で使うと言うか
732 :
723 :2010/10/18(月) 22:49:34
>>731 そういうのは入れ子とは言わない
Functionから別のFunctionを呼び出しているだけで、それは何も問題もなくできる
>>731 ただのcallingじゃねぇかYO!!
csv出力処理をwrite使って書いたのですが レコード毎にダブルクォーテーションで括られてしまいます Replace(hoge,"""","")でも消せない write関数がダメなんですか?それとも仕様? 因みにhogeはstringを繋げた文字列です
vba write ダブルクォーテーション でぐぐればそのものズバリのサイトが一番上に出てくる
すみません質問させていただきます。 数年前に退社した先輩社員の作ったマクロを解析したいのですが、 パスがかかっています。 バイナリデータにしてDPB=以降が確認されました。 そこで自分で作ったマクロつきのエクセルを同様にバイナリデータにしてみましたが、 DPBの文字列が確認できません。 マクロを開こうとするとちゃんとパスを聞いてきますので、パス設定はできていると思うのですが、 DPBの文字列がないのはどうしてなのでしょうか。 どなたかわかる方よろしくお願いします。
プロテクトがかかっているものを無理やり開きたい = クラッキングの方法を教えろになるわけですが。 (知らんけどw
>>738 保存したExcelのバージョンが違う
>>739 質問を最後までよく読め
そんなだから受験に失敗したんだよ
パスがわからないから、パスワードを調べる方法を探してるみたいだけど
最終的な目的はともかく、質問は下から2行目だろ
パス表示しないのは、のぞき見防止でしょ
パスは最初からどこにも表示されてない
文字入れても*も表示されないとか?
746 :
デフォルトの名無しさん :2010/10/19(火) 16:06:33
test
A.xlsというブックを開いた時にB.xlsというファイルが開いているかを 確認し開ていない場合には、ファイルを起動する様なコードが書きたいのですが A.xlsのオープン時にイベント処理を記述するにはどうすれば良いでしょうか?
おっと自己解決しました。
749 :
736 :2010/10/19(火) 22:57:14
>>737 ググったけどわからないから書き込んでるんだけどね
レコード単位で括られるのが普通なの?
>>749 は
>>737 に謝っとけ。
> この記述で動作させると、出力されたCSV形式テキストファイルは、セル値が日付の場合は「#」で囲われ、
> 文字列の場合はダブルクォーテーションで囲われて出力されます。
> まあ、これがVBAから出力されるCSV形式テキストファイルの「標準」ということなのでしょう。
> この方法ではこれらを変更することはできません。
>>749 > レコード単位で括られるのが普通なの?
CSVに厳密な「普通」はないよ
「カンマでデータが区切られている」以外の統一規定がない(あいまい)
これも同じページにきっちり解説あるじゃん…まさにググレカス
Dim fileNo As Integer fileNo = FreeFile Open "C:\aaa.html" For Append As #fileNo Print #fileNo, txt Close #fileNo HTMLを作成してこの中にどんどんExcelの文字を書き込むと言う事をしたいのd菅 このままだと文字化けがおこるみたいで これをutf-8、さらにBOMをつけるという形式で で保存したいのですが VBAで可能でしょうか? 教えてください
可能です
VBAでポインタは使えないの?
使えない
>>752 charactor separated valueって感じになってきてない?
必ずしもカンマで区切られないって先輩が言ってた
758 :
736 :2010/10/20(水) 08:06:06
>>750 俺の欲しい情報じゃないです
確かにセルの値から出力していますが
"A","B","C"って状態ではなく
"A,B,C"って状態なんですよ
セル値をレコード単位で繋げて出力してるだけなんですけどね
このダブルクォーテーションはReplace出来なかった
ん?まさか、
だと思うけどstring型はダブルクォーテーションで括られて…!?
あれ?まさか、\(^o^)/
じゃあ繋げた文字列からダブルクォーテーション取れないの?\(^o^)/
>>757 コンマの略ですらない場合(実際Tabだったり)もあるのは知ってるけど、
CSVとだけ言ってコンマ区切りじゃなかったら怒られるレベルだと思うw
760 :
736 :2010/10/20(水) 08:13:30
>>737 …すいませんでした
少し考えてみます
stringをvariant(0)に入れて…
762 :
デフォルトの名無しさん :2010/10/20(水) 10:06:10
>761
TSVとは【Tab Separated Values】(タブ区切り) - 意味/解説/説明/定義 : IT用語辞典
ttp://e-words.jp/w/TSV.html によりますと、TSVという形式の名称はあるようですが、拡張子は定まっていないということです。
>757
カンマで区切るからCSVであって、カンマ以外で区切ったらCSVとは言わないのでは?
(上記のTSVとか固定長ファイルとか)
データ形式と拡張子は別物w
TSVの拡張子で吐くシステムって、AS/400とか?
どっちにしろ人間が読みやすいだけの厄介なフォーマット 素直にExcel形式にするのが正解
今時、固定長のが扱いにくいと思うけどな xlsなんてオープンソースだと制限多くて使えない
XMLがいいよ。
それには同意
今はちょとしたツールの出力形式の話でしょ? データ交換に相応しい形式は何かでは無いよ 関連付けがIEのXMLで出力されるのは勘弁
さすがVBAスレ
そう褒めるな 照れる
772 :
デフォルトの名無しさん :2010/10/20(水) 14:12:41
メール送信・受信VBAを作ったなりよ アドオンで既存のExcelに機能追加できるなりよ。 これで、Excel作業中にメールチェックできるなりよ。 だれか、いる人いるなりか?いるなら、うpしようと思うなりよ。
いらねぇw
えー、俺欲しいな。 件名とか送り主とかを簡易DB化できるやんけ。
XP/Excel2000からWin7-64bit/Excel2010-64bitまでカバーしてるなら欲しい
現在ではCSVにも一応国際規格が存在するんだが いまさら特に守る理由もないし、古いアプリは当然従ってない 結局従ってないCSVを扱わないといけないという現実は変わらない
CSVがそもそも大した事ないんだから当たり前だろw それに最大公約数的な定義を明確にしただけだからね だがわりと重要なことも既定されてるんだ 改行コードはCRでもLFでもなく、CRLFであるべきとか ダブルクォーテーションの囲みなしでダブルクォーテーションが出現してはならないとか
>>775 アウトプロセスにロジック押し込んでExcelがUIって感じならいけるかな?
それか、まだ現役ならMAPI
>>772 欲しい!(^q^)
会社でExcelばっか起動してるし
よく作れたねー
形式的な1行のデータを表に纏めています。 フォームで入力して表に追加したいのですが、印刷もする為に罫線も自動で追加したいです。項目毎と底に太線を使います。 罫線はどうやって入れればいいですか? あと合計件数を多めに範囲指定してsubtotalで出していますが、いずれ増えるので、データの1番下を取得して指定したいです。 すみませんがお願いします。
>>781 底に太線を引く
With Range("A1").Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlMedium
End With
一番下を求める
xlDown
ありがとうございます。
Excel2003です VBAでワードアートの色を設定する方法は分かるんですが、(以下のような感じ) Selection.ShapeRange.Fill.ForeColor.SchemeColor = 2 塗りつぶし効果で既定の色(クロムとかサファイア等)を設定するにはどうしたらいいですか?
>>778 改行コードがcr+lfであるべきとするとプレーンテキストとの相互運用性が下がるじゃなイカ?
ネットワーク転送時もテキストモードからバイナリモードに変えねばならん
>>785 改行コードがcr+lfであるべき、ってのはフィールド内の改行を
有効にする場合のよくある手順じゃないの?
cr+lfがレコード区切り
lfがフィールド内の改行
当然ながら、最初からバイナリ運用が前提
>>785 778だけど、そうやってみんな自分の都合で簡便にCSVを利用したがるのが実情
だから5年たった今でもいろんなCSVに悩まされるわけで
RFCのは「全部こうだったらいいなぁ」という「願い事リスト」に過ぎない
RFC4180を知ってる人自体少ないからな、それ自体知らない人ばかりじゃあな…
そらRFCは元々壮大なローカルルールの公開場でしかないが、CSVはいまだローカルルールに過ぎん
今後これ以上発展する素養もないし、現状のまま続くか収束するか、いずれかだな
一応日本語訳貼ってみる(KASAIさん訳)
ttp://www.kasai.fm/wiki/rfc4180jp
だから、これからはXMLだって言っている。 CSVはマジであり得ない。
>>788 2005年10月に公開された RFC4180がどうかしたの?
>>786 もともとダブルクオーテーションで囲まれたフィールドはその中に改行入れられるがな
>>791 そうとは限らんだろう
ダブルクォーテーション内部に改行を入れても良いかという点もローカルルールだろうに
真っ先に1行単位で区分けして処理されてしまったらどうなるか分からん
>>789 だから、誰も否定してないだろ
>>790 …何が言いたいん?
>>789 いや、KVSが今の流れだろ
CSVネタがこんな続くと思わなかった
794 :
デフォルトの名無しさん :2010/10/25(月) 11:57:09
どなたかお知恵を拝借させていただけませんか? ○ ○/△/□ ○/□/△ □/△ ○/△ ○/□ △/□ △/□/○ △ □ ○/△/□/× × 上記のようなデータがあり、/を階層と呼ぶとして 最終階層を残し、重複する上位階層の行を削除するというマクロを作りたいのです 具体的な例: ○/□/△、□/△、△/□/○、○/△/□/×、×が最終階層だと判断 ○、○/△、○/□、□、△、△/□、○/△/□の行を削除 こういった処理をしたいのですが、どうすれば良いのか教えてください 行数が多いため、手作業でやるとなると膨大な時間がかかります… よろしくお願いいたします
使え
いや全角スペース使え
>>794 説明するスキルをもう少し頼む。
要するに「重複するパスを排除したい」でおk?
完全一致だけではなく「先頭からの部分一致」も重複とみなす。
で「残すのは最も長いパスのみ」であると。
パスは同不順で並んでいるようだけど、これには完全な重複も有り得るの?
たとえば8番目に△/□/○が出現してるけど、再び20番目に△/□/○が出現、さらに30番目にも出現とか。
仮に複数回出現するとなると、その場合どれを残したいの?(どれでもいいの?)
DOMを使ってツリーを構築すれば自然に重複は除去されるな
>>797 説明下手で申し訳ありません
> 要するに「重複するパスを排除したい」でおk?
おkです。そして、
>残すのは最も長いパスのみ
そうです、その通りです。
パスという言葉を使っていらっしゃるのでもうご理解いただいているようですが、
並び方が違う場合は別のパスと判断します
完全な重複は有り得なくはないです。もしあった場合はどれが残っても構いません
ああ、反応いただけて幸せです。どうかご教示お願いいたします
Excel2007 VBEでヘルプを見ようと一番上にある?マークのアイコンをクリックすると 一瞬Microsfot Office Onlineからの読み込み中となり このページはご利用いただけません となります。 これって変える事出来ないの? 要は、Excel 2007 開発者用リファレンス がすぐ出てくるようになれば いいんですけど。
>>794 階層毎の内容がサンプルのように全て同じ長さという前提だけど、
全体にソートをかけた上で、上から順に次の行と比較して
現在の行の内容を内包・一致の何れもしていない時は
最終階層と判断する方法があるな。
少し凝った処理をすれば、同じ長さである必要性もないけど一寸面倒。
802 :
794 :2010/10/25(月) 20:39:40
>>801 ご提言ありがとうございます!それが同じ長さじゃないんです‥‥
配列?dictionary?うーんわからん
803 :
801 :2010/10/25(月) 21:12:42
自分で書いといてなんだけど、同じ長さでなくても全く問題無くね? ○/△□が○/△を内包している、とか誤判断されるのは 末端に強制的に区切り記号を付ければ解決できるし。
yaoi
>>794 ちょっと変わった方法でコーディングしてみた。
書き終わったら思いのほか長くなってた、すまん。
作ってみて気に入らないところ:
1.最初のループ部分(Forループせず一発で全テキストを取得する方法ないかしら?)
2.Unionのエラートラップ(空のRangeオブジェクトを事前に作れるならOn Error要らなくなるんだけれど…)
ここもう少しスマートな書き方ないですかね?
以下に、コード。
…長すぎて書き込めなかったw 飯食ってから後で出直しまス。
codepadに貼ってよ
808 :
794 :2010/10/25(月) 21:37:55
>>803 なるほど、長さってそういうことですか!
確かに末端に付ける区切り記号を/以外にすればソートでなんとかなるかもしれませんね
>>806 ありがとうございます、楽しみに待っています!
805です。縮めようとしたら思いのほか面倒だったので 結局そのまま分けて書き込みまスw 以下コード前半&後半。 Sub ShortPathDelete() Dim i As Long, j As Long, Max As Long Dim JText As String, SText() As String Dim Target As Range, DelRange As Range Const cstSep As String = vbCrLf '一時的にパスを区切るための文字列(パスに出現しない文字列なら何でもおk) Set Target = Range("A1:A24") '検査範囲の指定(縦1列のみ対応) '事前準備フェーズ Max = Target.Count '検査範囲のセル個数の取得 ReDim SText(Max + 1) '一時的な配列。要素は2個多めに用意(区切り用) For i = 1 To Max '検査範囲を全ループ(単に全セルのTextを収集) SText(i) = Target(i).Text '1セルの値を取り出し Next JText = Join(SText, cstSep) '収集したパス配列を連結し1つのStringを作る(検出用作業データ) j = 1 'JText内の現位置(の終端)を格納する変数
'重複検出フェーズ For i = 1 To Max 'STextを全ループ j = j + Len(cstSep) + Len(SText(i)) '現位置(の終端)を算出 If InStr(j, JText, cstSep & SText(i) & cstSep) Then '現セル以降に完全一致がないか探す On Error GoTo UErr Set DelRange = Union(DelRange, Target.Worksheet.Rows(Target(i).Row)) '見つかったなら、自分は不要と確定 On Error GoTo 0 'Target.Worksheet.Rows(Target(i).Row).Interior.Color = vbRed ElseIf InStr(1, JText, cstSep & SText(i) & "/") Then '「セパレータ+現パス+/」の文字列を探す On Error GoTo UErr Set DelRange = Union(DelRange, Target.Worksheet.Rows(Target(i).Row)) '見つかったなら、自分は不要と確定 On Error GoTo 0 End If Next DelRange.Delete '不要な行を最後に一括デリート(行削除フェーズ) Exit Sub 'マクロ終了 UErr: 'エラートラップ Set DelRange = Target.Worksheet.Rows(Target(i).Row) 'はじめの1回だけエラーが起きるのでその対処 Resume Next '元のコードの次行へ戻る End Sub いじょ。
他にもDictionaryオブジェクト(またはCollection)を使う方法もあります。 コードはそっちのほうがはるかに短いし、分かりやすくなると思うけど、 こうやったほうが速くなるかも?と妄想してたらすでにそっちのコードが出来てました。合唱。
812 :
794 :2010/10/25(月) 22:45:15
>>811 ありがとうございます!
初心者レベルなので関数とアルゴリズム理解するのにちょっと時間かかりそうですが
明日の仕事までには解読して生かしたいと思います。本当に助かりました
>>812 急ぎなのに分かりにくい遊びコード書いて悪かったw
とりあえず、Targetに対象のセル範囲を渡して下さい。
例えば選択範囲を元に処理を行いたいなら、Selectionを渡すようにします。
Set Target = Selection
また各パスは/で終わらない事と、改行が含まれていない事が前提条件になってます
パスが/で終わっている場合はおそらく必ず残ってしまいます。
一時的な区切り文字は何でも構いません。
サンプルで改行を用いたのはデバッグやステップ実行でのチェックを容易にするためです。
パスに改行が含まれている可能性がある場合は、冒頭のConstを他の出現しない文字(例えば使っていない制御文字など)に置き換えて下さい。
パスとか何とか考えずに普通に文字列で比較したらダメなのかね? こんな感じで Sub test() Dim ans() As String ReDim ans(0) For Each c In Range("a1", Range("a1").End(xlDown)) s = c.Value addF = False For i = 0 To UBound(ans) If Len(ans(i)) < Len(s) Then If ans(i) = Left(s, Len(ans(i))) Then ans(i) = s addF = True End If Else If Left(ans(i), Len(s)) = s Then addF = True End If End If Next If Not addF Then ReDim Preserve ans(i) ans(i) = s End If Next つづく
815 :
794 :2010/10/25(月) 23:10:16
>>813 了解です。出勤したらダミーデータで試してみて、改良が必要なら加えて試してみます
やったねパパ、明日はホームランだ!!
後半は行除去してるだけだからまあどうでもいいけど つづき r = 1 Do Until Cells(r, 1).Value = "" delF = True For Each s In ans If Cells(r, 1).Value = s Then delF = False End If Next If delF Then Rows(r).Delete Else r = r + 1 End If Loop End Sub
817 :
814 :2010/10/25(月) 23:15:48
A列に上から順に隙間なくデータがある前提 ReDim Preserve がどうとか 変数が宣言されてないとか コードが汚いとかいう突っ込みは禁止なw
818 :
794 :2010/10/25(月) 23:19:34
>>817 変数宣言はまあVBAなんでw
コードが汚いなんて滅相もありません。俺のコードなんてスパゲッティどころか陰毛です
こちらも勉強しつつ試させていただきます。本当にありがとうございます!
陰毛w
>>815 一応
>>809-810 の内容もちゃちゃっと説明しときます。
概要は、すべてのパスから成る1行1パスの大きなテキスト(検出用作業データ)を1つ作り、
そのテキスト内を1回検索するだけで重複を一気に判定する、という仕組みになってます。
Join関数はString配列を全部くっ付けてくれる関数で&演算子で連結するより高速な良い子です。
SText配列は意図的にセルの数より2つ多く用意しています。(後述)
Joinの結果として、このテキストでは先頭と最後尾に空行が1つずつ出来ています。
あるパス(A/B)を含む長いパス(A/B/C)というのは、その前方がA/Bと完全に一致しさらにその後に/が続くものです。
よって、テキストの中を「A/B/」で検索すればよい事になります。もし見つかればこのパスA/Bは不要と確定します。
ただし行頭以外での部分一致も有り得るため実際には「改行A/B/」で検索をかけます。
(1つ目のパスの前にも空行を入れているので、すべてのパス先頭には必ず改行文字が存在する事になります)
あるパス(A/B)と完全一致するパス(A/B)は、当然「A/B」で検索できますが、別パスの中間とも一致してしまう可能性があります。(X/A/B/Zなど)
よって、実際にはテキスト中を「改行A/B改行」で検索します。もし見つかればこのパスは不要と確定します。
(最終パスの後ろにも空行を設けているので、すべてのパスは必ず改行に挟まれている、つまり改行でクォートされている事になります)
またこの検索はそのパス以降のテキストから行い、自分自身とチェックが完了している前方を除外します。
(変数jの計算はこの検索開始位置を決定するために行っています)
で、最終的に削除対象の行はDelRangeオブジェクトの中に格納されていきます。(Unionメソッドでどんどん連結してます)
最後に、DelRangeのDeleteメソッドで一気に削除してます。
以じょ…あ、削除行が全く見つからなかった場合のエラー対処忘れてルw
こんな感じに書き換えればいいかな↓
If Not DelRange Is Nothing then DelRange.Delete '不要な行を最後に一括デリート(行削除フェーズ)
アドインだかアドオンを作ったのだけど機能しない エクセル起動時にSendkeysで同じパスワードのエクセルを開く時パスワード入力を自動化おいしいです(^q^) ってのをやろうとしてる アドオンにする前はSendkeysが送出出来てる模様。アドオンにするとダメ パスワード手動入力後にSendkeysが走ってしまう 試しにMSGBOX入れると、こいつはパスワード入力ダイアログの前に表示される Excelの仕様?バグ? 何とかしたい
データが多いって言ってるのにunion使うなんて正気の沙汰じゃないね。
&演算子で連結するのが遅いのは知ってるのにUnionで非連続セルの連結がさらに輪をかけて遅いってのを知らないのは片手落ちだったね。
全く意味がわからん
再帰使えば簡単じゃね?
>>794 並び替えてフィルタオプションで出来ないか?
検索条件範囲がc1:c2なら
c1:
c2: =LEFT(SUBSTITUTE(A3,A2,""),1)<>"/"
でどこかに抽出すりゃいいと思うんだが。
上のC2ではうまくいかないかも知らん。 そんときは =LEFT(SUBSTITUTE(OFFSET(A2,1,),A2,""),1)<>"/" と汁!
>>824 とにかくunionが遅いってのを覚えときゃいい
830 :
794 :2010/10/26(火) 09:54:11
おはようございます
さっそく
>>809-810 様と
>>814 ,816様のアルゴリズムをダミーデータでテストさせていただきました
行数が少ないダミーでやってみましたが、双方ともちゃんと削除されました!
あとは完璧に理解して確信を持てた上でちょっとだけ改変し本番に臨みます
ム板最高!
>>826 前述している改変というのは、実は判定したいデータはB列にあり、
A列 B列
a ○/△
a △/×/□
a ○
a □/△
…
b □/○
b ○/△/□
b ×/△
……
のようにデータが入っていて、aにおいてB列の重複する短いパス(が含まれた行)を削除、同様にbにおいて重複するパスを削除…
のような形にしなければいけないのです
ソートキーを複数取ればいいだけの話かもしれませんが、できればマクロでいっぺんに済ませた方が気が楽なんです
>>829 ABC
ABCD/EF
とかになってるとまずいんだよね。
833 :
794 :2010/10/26(火) 10:17:06
>>832 あ、そか。頭いいですねえ。俺が頭悪すぎるだけですね。すみません
ぶっちゃけますとワークシート関数は全く知らない(俺はWEBデザ…)のでちょっと調べてみます
「検索範囲がC1:C2なら」の意味すらよくわかっていません。C列1行目&2行目?
いえ、どの方法であろうと最終的にできれば良いんです。皆様本当にありがとうございます
Excel上でソートして(行順が大事ならソート前に行に番号振っとく)
マクロ上で文字連結して
>>827 のワークシート関数呼び出して使い、
falseだったら行削除ってのが一番スマートな気がするw
>>821 パスワード入力ウィンドウがモーダルダイアログなら自前のVBAでやるのは無理だと思う
もう一つExcelを起動するとか、uwscみたいな自動運転フリーウェアでも使ってみたら?
>>834 なんの工夫もなく行削除はスマートじゃない。
書いてるとおりにフィルタオプションで別のところへ抽出するか、どうしても削除したければ827の式を
ズラッと入れて値貼りつけしてから、式を入れた列をキーにソートして、固まったFALSEを削除だな。
ばらばらの領域を削除は駄目。
>>836 の補足だが、作業列にズラッと入れるなら
>>826 の式でよい。
検索条件範囲の式ならA3が多分使えないからOFFSET(A2,1,)を使う。
809-810です。
Unionメソッドってそんなに遅いのか…めったに使わないので知らなかったw
貴重なツッコミサンクスです。
行削除は順序によっていろいろ面倒が起こったりする(二次災害的バグとか)ので
改変されても問題になりにくいよう配慮したという意図もあるんですが、
にしても1行ずつDeleteメソッド呼ぶよりは早いに違いないと思ったのに…Unionがどんだけ遅いのか試してみよ。
>>833 > ぶっちゃけますとワークシート関数は全く知らない
ExcelワークシートはダメだけどVBAならなんとかわかるって質問主は珍しい…w
WebデザならJavaScriptやASでプログラミングに慣れてるのかな。がんがれー
809-810です。
Unionメソッドってそんなに遅いのか…めったに使わないので知らなかったw
貴重なツッコミサンクスです。
(&演算子が遅いのを知ってるのは俺がVB6プログラマーだからです)
行削除は順序によっていろいろ面倒が起こったりする(二次災害的バグとか)ので
改変されても問題になりにくいよう配慮したという意図もあるんですが、
にしても1行ずつDeleteメソッド呼ぶよりは早いに違いないと思ったのに…Unionがどんだけ遅いのか試してみよ。
>>833 > ぶっちゃけますとワークシート関数は全く知らない
ExcelワークシートはダメだけどVBAならなんとかわかるって質問主は珍しい…w(俺もそっち側だけど)
WebデザならJavaScriptやASでプログラミングに慣れてるのかな。がんがれー
しかし、きめぇな
>>821 > Excelの仕様?バグ?
Windowsの仕様かと。つかSendKeysステートメントならそういう動作で正常なんじゃない?
> 試しにMSGBOX入れると、こいつはパスワード入力ダイアログの前に表示される
ということはタイミングも間違えてるよね(早すぎる)。SendKeysは扱い難い。確実に入力可能になるまで十分な待機が必要、つまりいつ呼ぶかが重要。
参考:
ttp://www.atmarkit.co.jp/fwin2k/operation/wsh05/wsh05_04.html ただ、モーダルウインドウが出現するとその親ウインドウは一時停止状態になる。
アドインはExcelの一部として動いているので、パス入力ウインドウが現れた時点で
アドインも止まっちゃうんじゃないかな?
結局外部から制御するしかないんじゃない?(ようするに
>>835 と同じ意見)
ダイアログが出現する直前は捉えているようなので、そのタイミングで外部の何かを呼ぶだけの話だけど。
VBScriptでもSendKeysは使えるので、アドインからはVBSを呼び出してみてはどうかな?
VBS側コードで適切にSleep待機した後、同じようにSendKeysするだけ。
>>833 ワークシート関数を知らなければVBAでやればよい。
SUBSUTUTEはReplace関数で似たようなことは出来る。
ようするに手順を考える力さえあればどうにでもなる。
>>842 つーかアドインじゃなきゃ大丈夫って書いてあるぜ?
846 :
821 :2010/10/26(火) 23:50:52
>>835 モーダルだと止まってしまうんですか
知らなかった
>>842 おお!VBSを呼び出してSendkeysは全然頭になかったです
重いファイルのExcelの時はsleep長めにしたりして調節してみます
有り難うございました!
847 :
844 :2010/10/27(水) 00:56:53
>>847 Sendkeysはわかっててもマウスとかキーボードとかついさわっちゃうんだよな
処理が終わるまで待ってるうちにメールでもチェックしようかとかつい思っちゃう
結局、何もできないのは実用性低いからウィンドウハンドル取得してメッセージ送るライブラリ作ったわ
>>847 ってVBSじゃね?VBAで作ったのをアドオンとして使いたいんじゃないの?
UserFormのTextbox(IMEModeはOn) にひらがな1文字だけ入れる欄をつくったんですけど、ひらがな1文字("あ"から"わ"まで)以外 はデータ入力エラーとして弾きたい どの様にチェックかければいいんでしょうか? まさか If Textbox1.Text <> "あ" And ~ なんて全部書くのもどうかと思うのですが。
>850 文字コードの範囲を調べたらいいのでは? 文字コードの並びの途中になにか漢字や記号ってあったっけ?
852 :
850 :2010/10/28(木) 17:02:08
すんませんでした 1) Select Case TextBox1.Text Case "あ" To "ん" MsgBox "ひらがな" End Select 2) If Asc(TextBox1.Text) >= -32097 And Asc(TextBox1.Text) <= -32015 Then MsgBox "ひらがな" Else MsgBox "Not ひらがな" End If で出来ました。 スレ汚し、ご容赦の程を
>>851 文字コード使うまでもないだろうに
正規表現で簡単に弾けるのに
>>850 >> Case "あ" To "ん"
あ、こんな書き方も出来たんだ。勉強になった、ありがと。
>>853 正規表現知ってるならそう言えるかもしれないけど、
知らない段階だと今回の結果を得るまでの道のりは長いと思うんだ。
一応参照設定しなければ扱えないし各オブジェクトの知識も必要だしね。
まぁ正規表現知ってる身としては同じこと思ったよ。
でも「文字コード使うまでもない」って言い回しはなんか間違えてると思うw
どっちかっつーと「この程度の事で正規表現使うまでもない」よ。
超初心者なのですが、半角の・や/~,:;などをエクセルの特定の列には 入力できないようにしたいのですが、そもそも可能なんでしょうか? こんなど素人な質問ですみませんが、どなたかご教示下さい。
>>852 コード順だと、ひらがなの最初の文字は「あ」じゃなくて「ぁ」だよ
>>855 入力直後、セルの内容が確定した瞬間にエラーを出すことならできる
VBAのモジュール内にコードを追加する場合 参照設定するんだけど、それ以外に何か方法あります? 配布するのに、参照設定をVBAから制御しようとするとエラーが出る・・・ので。
日本語で頼む
遠いなおい
>>859 の間違いだった。どうせだから追記。
参照設定自体はなくせる。(CreateObjectなどを使う)
ただしコーディングの補完や事前型チェックが行われない。
「モジュール内にコードを追加する場合」って何を指してる?
VBAからVBAのコードを追加するって事か?
VBAから参照設定を行おうとしているって事か?
よくわからん。
エクセル2010のVBAをつかっています。 マクロで、関数をつかった数式の中の文字列の一部を違う文字列に置き換えたいのですが、 Left(, )などをつかうと、セルに表示される結果のほうにマクロがきいてしまい 関数を含む計算式のほうの文字列にはききません。 行き詰っています、助けてください。
>>863 そりゃLeft関数は冤罪だろ。
原因は.Valueプロパティや.textプロパティを参照・代入してるからだ。(Rangeは省略するとValue扱いじゃなかったっけ?)
数式をどうこうする場合は.Formulaプロパティを参照して置換して代入すべし。
865 :
855 :2010/10/28(木) 23:44:45
>>857 >>858 レスありがとうございます。
入力規則で調べてみたのですが、なんか1種類の文字しか入力不可にできなくて…
できれば、ヒントなどを教えていただけると大変ありがたいです。
テキストボックスで未入力の時だけ色を付けたくて関数作りました テキストボックスは20個くらいあるんですが、全てに適用するには一つ一つchangeイベントを作るしかないでしょうか
>>866 Textbox01、Textbox02、みたいに連番でオブジェクト名が付いてれば
工夫次第でプログラムを簡潔に書けることもある
>>865 入力規則の条件式にはあまり複雑なものは書けないみたいなので
ちょっと無理をする必要があるかも
=AND(ISERROR(FIND("/",B4)),ISERROR(FIND("~",B4)),ISERROR(FIND(",",B4)),ISERROR(FIND(":",B4)),ISERROR(FIND(";",B4)))
とか
上は対象セルがB4の場合の例
869 :
855 :2010/10/29(金) 06:52:28
>>868 ありがとうございます!
やってみます!
>>866 つユーザーコントロール
でもVBAじゃ作れないしその程度であれば20個書いた方が良いと思う。
ActiveControlに作用するメソッドを呼ぶ形にすれば20行で済むし。
ActiveControlがVBAにあるかは知らないけど
>>854 あんたに取っては正規表現より文字コードのが敷居が低いと思ってるし、この程度の処理で正規表現は使うまでもないと思ってるだろうけど
俺は全く逆だわw
例えばよくある話で弾きたい文字列がコロコロ仕変される事を想定して正規表現で柔軟性を持たせるとかね
人によって考え方は違うんだろうけど
あんたのお陰でまた1つベストプラクティスが増えてしまったぜw
thx
おまいら下のコード動く? 一番下が何故か動かない。 どぼじで? Sub huga() hoge try1 Application.Run "hoge" Application.Run "try1" 'ここが動かない End Sub Private Sub hoge() MsgBox "呼んだ?" End Sub Private Sub try1() MsgBox "呼んだ?" End Sub
>>872 Excel 2003 動いた
Excel 2007 動かない
>872 標準モジュールに書いたら 呼んだ? が4回表示されました。 シート1に書いたら 呼んだ? が2回表示され、次はエラーになりました。 シートに書いたら、シート名の修飾をつけないと特定できません。 Excel総合相談所 93(現スレのひとつ前)の658で似たような質問がありました。
875 :
874 :2010/10/29(金) 09:38:51
>872,873 リロードしてなかった 当方、Excel2003なので状況違うのかな? hoge と try1 の違いは数字の有無の違いだけなので、ここがExcel2003と2007で扱いが違うのかも。
>>872 色々試してみたら、これだと2007でも動くんで、「try」という名前が使えないっぽい
理由は不明
Sub huga()
hoge
tryy1
Application.Run "hoge"
Application.Run "tryy1" 'ここが動かない
End Sub
Private Sub hoge()
MsgBox "呼んだ?"
End Sub
Private Sub tryy1()
MsgBox "呼んだ?"
End Sub
○ ttry1 ○ tryy1 ○ hoge1 × try111
"try_1"なら動くね "try9"はエラー "try0"なら動く "try01"はエラー "try10"もエラー 何かのオブジェクト名と衝突してるわけでもなさそうだ
879 :
872 :2010/10/29(金) 10:04:20
>>873-878 トンクス
動かないのが俺だけじゃないのが分ってよかったぜ。
どうなってるんだろうね。
callで呼ぶかFunctionに変更すると動いた。 Application.Run使うってことは他のブックの変更できないSubプロシージャでも呼んでいるの?
>>880 いやtry1~try10を順番に走らせただけ。
for i = 1 to 10
application.run "try"&i
next i
別に
try1
try2
.
.
try10
と列記してもいいんだけどね。
単にブック名とモジュール名で修飾してないだけでは?
>>862 次の作業を行うためにreferenceを使ったんだが、動かなかった
そうかCreateObject使えば良かったのか
VBAから、VBAのコードを記述する
例えば
sub hoge()
を
sub hogehoge()
に書き換える
Microsoft Visual Basia for Application Extensibilityの参照設定を行い、VBEID.VBProjectで宣言をする
あまり行数変わらんな 'Module1.bas Sub Hoge() Dim try As New Class1 Dim i As Integer For i = 1 To 10 With try .Number = i .Piyo End With Next End Sub 'Class1.cls Public Number As Integer Sub Piyo() MsgBox "呼んだ?" ' Debug.Print Number & "呼んだ?" End Sub
Tryは例外処理とぶつかる
>>879 Application.Run "Module1.try1"
なら動くな(Module1に書いた場合)
2003で動いてたなら、2007で追加された何かと名前がバッティングしてるぽい
自モジュールより検索順位が高いものなんて何があるんだ?
try0→OK try1~try9→NG 何か未公開のメソッドとかあんのかな msdnも見たけど、普通にtry1を変数名に使ってるサンプルとか出てくるだけだし
文字列の変換で 1なら●に変換 10なら●●●●●●●●●● など ●かける数字に変換をしたいのですが これがだいたい300ぐらいまであるので、Case文などはつかえないので どういう風にすれば一番プログラムを書かずに実現できるが教えてください
890 :
デフォルトの名無しさん :2010/10/30(土) 15:30:07
>>889 パフォーマンス優先ならあらかじめ"●●●●●●●●●●●●●●●●"などと十分に長い文字列を用意しておきLeft$関数で取り出せば良い。
コードの行数優先ならばStringだな。
パフォーマンス優先でも"●●●●●●●●●●●●●●●●"を作るのに1回はStringを使うか。
894 :
デフォルトの名無しさん :2010/10/30(土) 20:15:23
worksheetfunction.rept(\\\"●\\\",n)
EXCELでリアルタイムに株価の銘柄ランキング表をつくっているんですが、 ランキングに(新しくランキングに新しい銘柄が出現)変化があった場合に、音で知らせる方法は どのようなマクロつかったらよいのでしょうか?
>>895 Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _
(ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
Sub 変化があったよ()
xxx = mciSendString("Play C:\Windows\Media\tada.wav", "", 0, 0)
End Sub
OPENしてなくてもCLOSEしとくべきじゃね
>896 ありがとうございます。工夫してやってみます。
ワークシートのある範囲(1行n列:例えばRange("C8:AE8"))を配列として取得して、要素(n)の数だけループしたいんだけど uboundでは要素数が 1 と判定されてしまうんだけど、nの求め方ってどうしたらいいんですか?
>>899 範囲の幅を求めるならRange("C8:AE8").Columns.Countだけど
ループする時は普通はいちいち数えないで
For Each C in Range("C8:AE8") ~ Next
って書くんだよ
ループを回して何をやりたいかで変わるわな。 配列をFor~Nextで回した方がいい場合もあればFor Each~ Nextで回した方がいい場合もある。
A1にセル内で改行されているデータをStringに入れて それを別のセルに出力したい場合 Stringに入れた時点でセル内の改行がなくなるのですが これを防ぐ方法とかあるのでしょうか? やり方を教えてください
本当に無くなっているのか?それ。 単に書式絡みで改行されていないように見える、とかじゃね?
いや無くなってるようです。 ちなみに途中でStringに入れられた時点の中身を見ても すでに改行コードはなく文字列は繋がった状態です。
俺の2007だと改行は残ってるけどなぁ。 どう言う方法でString内を確認しましたか?
Excel2007で Sub test1() Dim str As String str = Cells(1, 1) Cells(2, 1) = str End Sub でやってみたけど、A1のゼル内改行データがそのまんまの状態でA2に出たけどなぁ セル幅広げてみたら下に隠れていたとかじゃないだろうな
2003でも改行されたままだけど
2010でも改行コード残ってるぜ。 勘違いだろ?
911 :
kobozu :2010/10/31(日) 22:27:34
出力セルの書式設定をセルA1と同じにする、 即ち、”折り返して全体を表示”にする S = Range("A1").Value Range("B1").Value = S Range("B1").WrapText = Range("A1").WrapText
912 :
kobozu :2010/10/31(日) 22:42:37
改行コードを知れべてみればいいのでは? s = Range("A1").Value MsgBox InStr(s, vbLf)
>>906 変数に入れるだけで改行が無くなるなんて事は、絶対にないと言い切れる
あなたの検証のどこかに勘違いが存在する
> 中身を見ても
どうやって見た?
確認方法を検証する必要がある
もちろんDebug.printかMsgboxでチェックしたんだよな?
あと、ステップ実行中に変数へマウスを乗せた時に中身のプレビューが出るが
ここでは「制御文字は反映されない」という仕様だ
もし改行文字があっても表示上改行はされない
こういったいくつかの勘違いと
>>905 の組み合わせで勘違いしてるんだろうと思う
折り返して全体を表示する と セル内の改行(Alt+ Enter)と同じか?
>>914 >>911 へのツッコミか?と思うのだが、
彼はそもそも「元の文字列に改行が含まれていない可能性」を指摘している。
その可能性が濃厚ですな 実は改行してないってことか
917 :
kobozu :2010/11/01(月) 00:20:30
>>914 さん、
セル内改行は「折り返して全体を表示する」が前提でないと
成り立たないので同じことだと理解しているのですが。。。
(WrapTextプロパティがTRUE)
「折り返して全体を表示」するのは同じで、違いは
折り返しをExcel任せにするか、ユーザー任せにするか、だけだと。。
勘違いしてましたら是非ご指摘ください。
>>914 ,917
セル内改行はたしかに折り返して表示が有効になっていないと正しく表示されないかもしれないが
だからといって、折り返し表示されていることがセル内に改行が含まれている事を意味しない
十分にセル幅があっても改行されるのが普通に言うセル内の改行だぞ
StringってString型の変数じゃなくString関数だたりしてw
>>904 =FIND(CHAR(10),A1)としてみてちゃんと数値が返るか?
#VALUE!だったらセル内改行は含まれてないぞ
>>904 改行コードが化けているのかな?
そのファイル2003で作ったあとに2007で編集とかしてない?
replace(replace(hoge,vbLf,vbLf + vbCr),vbLf + vbLf,vbLf)
俺も以前改行が取り除けない事があってバイナリデータ調べて0D0Aになってない箇所があったから上の式に似た奴追記した
922 :
921 :2010/11/01(月) 08:53:57
肝心なところ忘れてたわ
君のケースでは改行コードが化けて欠落してるっぽいから
>>921 のコードを追記してみれば解決するかも
hogeの部分はstring変数ね
ほう、2007だとセル内改行はラインフィールドだけなの?
>>923 手でAlt + Enterならラインフィールドだろ?
わざわざキャリッジリターン+ラインフィールドを挿入する人いないだろうなぁ。
Line Feed
大抵のプログラムはLFだけ送ればそれに合った改行してくれると思うのだが
927 :
デフォルトの名無しさん :2010/11/01(月) 20:23:22
ExcelVBAで自己書き換えなんて出来るのか・・・
928 :
デフォルトの名無しさん :2010/11/01(月) 21:16:15
>>923 いや。互換性はあるんだが、コードが化けてしまう事象が発生した事があったのよ
確実な原因は分からないけど
>>926 普通はね
でもCrだけ残るって事が過去にあった
目視できないから気を付けて
余談だけど他人のソース読むと時々vbCr + vbLfってなってるのをよく見掛ける vbLfが入ってるから余り弊害ないのかもしれんが 本当に止めて欲しい
>>924 テキストやcsv等からコピペしたら0D0Aになるから何気に改行コードはちゃんと対応したほうがいいよ
vbCrLf って定数があるのに、 何で分けて書くの?
知らないからだろ
NewLineは少数派か?
テキスト出力するときはたまにNewLine使うが大抵はVBCrlfだなあ
937 :
デフォルトの名無しさん :2010/11/02(火) 08:54:20
ダブルクリックでセル内の文字を○印で囲み 再度ダブルクリックで○印を消すには? 太さは0.75、色は黒指定です。
>>937 Excelには囲い文字機能がないのでオートシェイプで代用
オートシェイプは、行や列を削除してもそのまま残る
Excel VBAにはダブルクリックイベントがない
BeforeDoubleClickeイベントを使うと、セルがいちいち編集状態になってしまう
使用する状況がかなり限定されてもいいのなら
できないこともないけど…
939 :
デフォルトの名無しさん :2010/11/02(火) 10:22:05
BeforeDoubleClickeイベントで Cancel = True にしたら編集状態にならないんですよね? 使用する範囲はB4:G12の限定です。
>>935 少数派だと思う。比較的新しい定数だし、乗り換える理由とかも特別ないので。
NewLineは何になるか環境依存と定義されてるので基本的に避けてる。(MacだとLF扱いだっけ?)
>>939 そうするとマウスから編集モードに入れなくなるわけだが、いいのか?
942 :
デフォルトの名無しさん :2010/11/02(火) 19:33:49
VBA歴2ヶ月の者です 質問なのですが下記のコードの 5行目のSheets(i).ActivateがSheets(i).selectだと最初のシートが35列下がるだけで 他のシートは変化が無かったのですがなぜでしょうか? selectで動作するよう書き換えるとすればどこでしょうか? よろしくお願いします Sub 全シートdown() Application.ScreenUpdating = False Dim st st = ActiveSheet.Name For i = 1 To Worksheets.Count Sheets(i).Activate ActiveWindow.SmallScroll Down:=35 Next Worksheets(st).Select Application.ScreenUpdating = true End Sub
>>942 エクセル2007だとActivate,Selectどちらでも動く
実行したら全シートちゃんとスクロールされてたけど…? (環境:Excel2000 + Win7 Ultimate 64bit)
945 :
942 :2010/11/02(火) 20:38:38
>>943 >>944 こちらの環境はXPでExcel2000だったと思います(帰宅後の為IDも変わっています)
当初selectでF8のスキップモードでは動作していて、実際にボタンに割り当てて使用すると動作せず
現在のactivate使用でも動作しなかったのですが
そのまま保存して再度ファイルを開いたら動作しました
動いたので良しとしたのですがイマイチすっきりしていなかったのです
コードは正しくてもエクセルを再起動させないと動作しないといった事はよくある事でしょうか?
>>945 まれによくある。
コードが動いてる最中に動的にそのブロック内を書き換えるという行為は、
実行側(Excel側)から見ると内部的にかなりややこしくてめんどくさい作業をしている。
実行中の関数や変数などに対して追加したり無かったことにしたりと厄介な手続きが多々あり非常に忙しい。
で、そこに珍しい不具合がいくつか潜んでいる。
ごく限られた条件の下で推移的に異常な状態になったりつじつまが合わなくなったりする不具合がある。
ちなみにこれは確率で発生するのではなく、ちゃんと要因がある。
中断タイミング、ワンステップ実行タイミング、コードの記述順、イミディエイトウインドウからの書き換え、ウォッチリストの影響、マウスを乗せて参照が起きたなど。
よってまったく同じ手順を踏めばまったく同じ不具合に再び遭遇するし他人も再現可能。逆に言えば把握していれば回避可能。
まぁ、遭遇した場合はExcelを再起動するなりファイルを閉じて読み直せば直る。
例えば実行中のブロック内でまずi=1というコードを書き、続けてどこかにDim i as Longと書くと変数名が重複しているという正しくないエラーが出たりする。
例ではDim行を書いた段階で実行中断を要求される(宣言コードは実行中に反映できないため)が、それに従い中断すると重複していないにもかかわらず「同じ適用範囲内で変数名が重複しています」のエラーとなる。
この場合は、暗黙のうちに行われた変数iの宣言が中断した後も内部的に有効のままになっているバグが発生しDim行のコンパイルはずっと失敗し続ける。
いったんiの参照をすべて消すかコメントアウトすると正しくDimが成功するようになり、再び完全に同一のコードに書き換えてもエラーは出ない。
前述のとおりこの場合もファイルを閉じて開くことでも不具合は直る。
>>940 逆でしょ
環境依存の部分を吸収してくれるなら使った方が良い。
でもMacなんかで動かさんし、みんな使ってないし。
まれによくある まれなのか、よくあるのかどっちだ?
>>947 書き方(考え方)が逆でもどうでもいいだろ。というかそんなお前も逆だ。
ExcelそのものがほぼWindowsへの環境依存状態なので配慮する意味がない。
意味がないので普及しない、普及してないからみんな使わない。
むしろ各改行コード混在を想定する場合などは使うべきではないだろう。
vbNewLineがvbLfともvbCrともvbCrLfとも一致でき、混在状態でも改行を正しく検出出来るという代物なら話は別だったが。
所詮vbNewLineはただひとつの改行コードの定数に過ぎないんだから。
(かといってvbCrLfと常に一致すると決まってもいない中途半端で使いにくい存在)
>>948 まれに、よくあるのだよ。
よく出会う人は出会うし、だが出会わない人はなかなか出会わない。
デバッガー内のわかりにくい不具合なのでまれに遭遇する人がいる。
だがこれに遭遇するような人は再び遭遇する可能性が高い、総じてまれによくある。
>>946 どうもありがとう
はっきりわかったわけではないですが何とかイメージできました
まぁまさかブロントさんに答えてもらえるとは思いませんでしたけどw
>>943 ,944さんもレスありがとう
光栄だ。しかしブロントさんは句点を使わないのだ。 よって逆説的にも俺はブロントさんではない。 俺は単なる長い丸の人だ。 1920x1200で最大化してサクサク書いてたら 行区切るのも長文自重するのも忘れてた。すまん。
Excel2007 ユーザーフォームにテキストボックスとボタン1個があります。 テキストボックスで入力を完了したら(つまりEnterを押したらで良いんですけど)、即ボタンを押したのと同じ事にするように したいのですが。
更新後処理かフォーカス喪失時処理かエンターキーのバインドかな フォーカス喪失はタブ移動でも処理してしまうから、条件処理しないとシステム的なフォームには使いづらいかも
>>952 Private Sub TextBox1_AfterUpdate()
CommandButton1_Click
End Sub
>>952 1行目の前提が崩れないならCommandButtonのプロパティにあるDefaultをtrueに変えればいいんじゃない?
956 :
952 :2010/11/03(水) 11:30:08
955さんの案でさせていただきます。 ところで、954さんの案だと以下で良いと思うのですが Module1に Public txt As String Sub formtest() UserForm1.Show MsgBox "txt:" & txt End Sub UserForm1(TextBoxとCommandButton1のみ)に以下のコードを Private Sub TextBox1_AfterUpdate() CommandButton1_Click End Sub Private Sub CommandButton1_Click() txt = TextBox1.Text Unload Me End Sub でテストしたら、文字を入れてエンターを押すと formtestの UserForm1.Show でストップ、 実行時エラー '-2147417848(80010108)' オートメーションエラーです。 起動されたオブジェクトはクライアントから切断されました。 てメッセージが orz
質問です。よろしくお願いします。 作成したマクロを、他のExcellファイルでも使いたい場合、 マクロのソースをコピペして持っていく以外の方法ってありますでしょうか?
958 :
デフォルトの名無しさん :2010/11/04(木) 00:05:56
エキスポートしてインポート
>>957 あとは、元ネタのソースを印刷して他のExcelで手打ちって方法もあるな
>957 特殊な使い方になるけど、VBAマクロを記録したブックとマクロの処理対象となるブックを別にする っていうことも可能です。両方のブックをひとつのエクセルで開き、処理したいブックを表にした状態で マクロを起動する方法です。 処理したいものが.csvとか、次々と処理対象が変わるなどの場合に便利です。
>>960 そういうのがアリなら
マクロを移すんじゃなくてデータを持ってきて, 処理したあと
また結果をカトペで戻すって手もあるな
963 :
デフォルトの名無しさん :2010/11/04(木) 19:02:00
個人用マクロブック(Personal.xls)に書けば万事おk
ブックのパスワードを自動入力するのをずっとやってる者です AppActivateで"パスワード"やら"Microsoft Excel"でパスワードのモーダルは掴めるんだけど SendKeysが送れない… と言うかアクティブになるまで長い時間ループしてるのに見付からないとなる 因みにアドイン化したマクロからVBSをShellで呼び出してます
965 :
デフォルトの名無しさん :2010/11/05(金) 18:53:59
まだそんなとこにいたんかいw パスワード入力ウインドウのhWndは取得出来たが、 アクティブウインドウとして捕捉出来ないって事? (だからSendKeysが呼べないと)
テキスト入力ができないんじゃなくて、パスワード入力ボックス自体が見つからないの? プロセス監視してフォーカス移すのはどうだ?
簡単に言うなお
Sendkeysはアクティブなオブジェクトにしか送れないから、 ウィンドウがアクティブでもパスワードボックスがアクティブになってない可能性は? Sendkeys使うのやめてキーボードイベント送ってみたら? これならウィンドウ自体が非アクティブでも文字が入力できるし 途中でうっかりマウスとかにさわっても影響受けないから
ブック開くときオプションでパスワードって送れないんだっけ あとは、擬似的なパスワード入力ダイアログを表示するのはどうか ブックオープン時に引数を渡し、渡されなかった場合はパスワード入力フォームを表示する。 ブックを開く際に、個人用マクロを調査し、擬似パスワードを表示するように 自動で書き換えて、条件判断する。
>>964 進んでねぇじゃんw
>>969 の言うように引数で渡せるし、大体処理のトリガーは何で、何を対象にパスワード解除するんだ?
ちょっと書いてあったか VBSに逃げようとする事自体が良くない上、 何とか出来るケースだとみんな思ってる アドインはいつ呼ばれるの? ボタンがあるの?
俺はVBA内だけ(APIやVBSなどを使わず)何とか出来ると思えないけど。 通常のファイルダブルクリックや履歴からのロードを最初のトリガーにしたいんでしょ? VBAがオープンするわけじゃないからブックオープン引数は与えられないし。 SandKeysの賛否はともかく、外部からどうにかするしかないのはほぼ確定でしょ。
>>964 状況を整理しときたい
パスワードは何に対してかかってるの?ブック?VBA?
パスワードの種類は読み取り?書き込み?
パスワードが自動入力される条件は?無条件だとパスワードの意味がないよね。
あとOSとExcelのバージョンは?
あらかじめ作成したファイルを、用意したエクセル経由以外で開こうとしたときに開かせないというなら、 ブックオープン時にコードを読み込ませて見えないようにしたり、開かないパスワード聞かせたりすればいいのでは VBAわかる人間なら使ってる鍵ファイルからパスワード読み出すだろうし、そうでないならVBAからのパスワードを突破できないだろうし
>>972 だが、俺の推測(というかこういう話だとしか思えない)
彼はVBAではなく、ブックのパスワードを対象にしている。
また彼は自分が作った複数のブックに同一のパスワードを使用している。
何度もファイルを開くだびにパスワードを入力したくないと感じている。
彼の考えたアドインはフォームを持たずユーザーのファイルオープンを監視して自動で動き、
Excelのパスワード入力ウインドウに対して処理を行おうとしている。
しかしアドインからは直接このモーダルウインドウを処理出来ないようだとわかり、その実コードを外部(VBS)に分離。
だが、結局VBSでも出来ないウワーン (←今ここ)
つまり推測が正しいならもはやVBAの質問じゃない。これはVBSの質問だ。
正直この方向で行くなら以降はVBSスレ(やVB6スレ)で聞けよ、って気もしている。
残りはVBA以外で「特定のウインドウの特定のEditBoxへ特定の文字を入力させる方法」を模索するだけなんだし。
VBプログラマ質問スレ(Ver.6.0 まで) part56
http://hibari.2ch.net/test/read.cgi/tech/1275397597/
>>972 ダイアログまで表示出来てるみたいからオープン時ではなさそう。
仮にそうだとしてもApplicationレベルのイベントはハンドリング可能。
>>976 あれ? パスワードがかかっているブックもハンドリング可能?
以前からそれが出来るって誰も言ってないんで出来ないんだろうと仮定してたが
出来るならExcelのパス確認出る前に解除しちゃえばいいだけじゃんw
ともかく
>>964 は何したいのか説明するスキルを磨けよ
レスしてくれてる人みんな、お前の前提がわかってないみたいだぞ?w
>>965 パスワードダイアログは間違いなく掴めてる
別のウィンドウをアクティブにするとループしてるからパスワードダイアログがアクティブになる
>>966 やっぱ起動時プロセスからプロセスID取得するしかないのかなぁ
でも、それだと、やりたい事が実現できないかも
>>968 キーボードイベント?ちょっと調べてみます
>>971 パスワードは読み取りパス
トリガはexcelを開く時に実行される何たらAuto()で実装してます。これをアドインにしてます
>>972 私も外部からじゃないと無理だと思ってます
>>973 > 状況を整理しときたい
>
> パスワードは何に対してかかってるの?ブック?VBA?
ブックです
> パスワードの種類は読み取り?書き込み?
読み取りです
> パスワードが自動入力される条件は?無条件だとパスワードの意味がないよね。
無条件ですが、とある指定したパスが掛かっていないのをSleepやカウウタで判断してスルーさせたいです
>
> あとOSとExcelのバージョンは?
XP SP3 office2003です
>>975 スレ違いすいませんでした
誘導有り難う…
お世話になったので出来上がったらソースだけでも公開します
ごめんなさい
説明する気がさらさら無いってことだけはわかった
>>982 他に何を説明すればいいんだ?
同値読み取りパスがかかったブックが複数あって、パスが掛かっていないブックもある
アドインにより無作為に選んだブックに対して必ずブックオープン時にイベントが走り自動で同値パスを入力する
パスワードダイアログがでない場合はスルーする
以上が仕様
オープン時にShellでvbsを実行する事は出来たがパスワードダイアログが上手く取得できない
ウィンドウ名でなくプロセスIDならvbsで上手く行くかも
だが無作為に選んだブックのプロセスIDをvbaで取得なんてできんの?
(無作為に選んだブックと言うのはファイル選択ダイアログ等からではなく、ファイルアイコンをダブルクリックで普通に開かれた場合)
出来るなら、そのプロセスIDをvbsに引き渡して処理が出来ると思う
つまり、vbaで現在開いているブック(excel)のプロセスIDが取得できますか?
出来ないのであれば他にどの様な方法で同様の処理が可能ですか?
上の説明で分からないのであれば
>>975 が全て正解
>つまり、vbaで現在開いているブック(excel)のプロセスIDが取得できますか? できます
>>983-984 協力求めるのがすこぶる下手な奴だなw でも嫌いじゃないぜ、俺975。
スレチだから出てけって意味じゃない。ここよりその話に強そうなスレを案内しただけ。
それに謝らなくていいよ。そもそもやりたい事はこのスレの範疇だと思うし。
ただ今欲しがってる情報は普通のプログラマーでないと答えられない。それを主に回答側へ周知したかった。
あの文面、半分はこのスレで協力しようとしてくれてる人へのメッセージだよ。
勘違いや無用な混乱が発生してた。それを止めようと思ってさ。
攻撃してる人だって協力しようとしてんのさ。ただ、質問内容が曖昧で自分が答えられるかどうかすら判断できない状況にイライラしてたんだよ。きっと。
ここはVBAスレだからWindowsに深い造詣を持ってる必要はない。実際そういう人は多くもない。(VB6/VB.NETやってるエロい人がたまに居るぽ)
「別プロセスのウインドウを外部からユーザーに成りすまして制御する方法」この言葉の意味がわかるひと何人いるかな。
ようするにこのスレには相対的に荷が重いのよ…あ、住人は馬鹿にしてないぞ。単に畑違いのスキル、知ってるほうがおかしい。
>>986 1ブック=1プロセスじゃないけどそこは大丈夫? 場合によっては1プロセスが複数のブック持ってたりする。
また実行中のアドイン自身がいるExcelのオーナーウインドウハンドルは、2003ならApplication.hWndで取れるらしい。(ちなみにうちの2000だと取れない)
ttp://msdn.microsoft.com/ja-jp/library/cc387509.aspx あとはAPIでhWndからプロセスIDを取得出来るんでそれでどうぞ。
GetCurrentProcessId
AutoOpenでVBS起動って2ファイル目以降どうすんだろ?
>>987 ブックとプロセスの問題を調べまつ
長文ありがとう
俺は人を信じてるだけだよ。 そして他の誰かがきっと次スレ建てると信じている。 よろしくw
Excel2003、VBAは動かすのはほぼやったことないです できればUserFormでは無くシート上がいいんだけど、オブジェクトを指定した場所に動かす (単に移動ではなく、動いてる様子みたいなのが見えるように) クリックした場所に移動とかではなく、B2に移動とかがいいです お願いします
994 :
デフォルトの名無しさん :2010/11/08(月) 11:16:45
>>993 こんな感じ?
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub Macro1()
SendKeys ("%{F11}")
st = 100 'Top ボタンの初期位置
sl = 200 'Left
dt = Range("B2").Top '移動先
dl = Range("B2").Left
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False, Left:=sl, Top:=st, Width:=64, Height:=32).Select
Sleep (500)
nw = 30
For i = nw To 0 Step -1
Sleep (15)
Selection.ShapeRange.Left = dl - (dl - sl) / nw * i
Selection.ShapeRange.Top = dt - (dt - st) / nw * i
DoEvents
Next
Sleep (750)
End Sub
ちなみに動かすもの"コマンドボタン"を"図1"に代えたいときはどうすればいいんですか?
nero
a
t
∧,,,∧ ( ・∀・) 1000ならジュースでも飲むか ( ) し─J
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。