Excel VBA質問スレ Part7at TECH
Excel VBA質問スレ Part7 - 暇つぶし2ch398:384
08/07/15 13:02:18
>>392
レスどうもです。
「セルを選んでください」の表示前にあったセル位置の情報しか取得出来なくて、

>3.シートに戻り、任意セルをクリックする。(セルが選ばれるまで先の処理に進まない)

この3番のユーザーの入力待ちがどうしても出来ません。

>>393
どうもです。
連続した作業になるので、メッセージボックスは1度だけにしたいんです。




399:デフォルトの名無しさん
08/07/15 15:42:46
VBAのソースコードをカラーで印刷する方法が判りません
印刷品質くらいしか選べなくてモノクロになっちゃいます
誰か教えてください・・・・

400:デフォルトの名無しさん
08/07/15 17:07:33
print screenで画像保存してそれをカラー印刷すれば良いじゃん

401:デフォルトの名無しさん
08/07/15 17:39:35
VBA初心者の者ですが、
(A:B)列のセルがゼロか空白ならば、
(1:50)の行が削除される構文をどなたか教えて頂けますか。

If Then Else ステートメントを使ってやるのでしょうか。
お願い致します。

402:デフォルトの名無しさん
08/07/15 19:20:29
>>401
たとえばC51セルに =COUNTIF(A:B,"0")+COUNTIF(A:B,"") と式を打っておいて


Sub セルクリア()

If Range("C51") = 0 Then

Else

Range("1:1", "50:50").Clear

End If

End Sub

これで一応できるよ

403:デフォルトの名無しさん
08/07/15 19:25:06
なんか間違えた
無かったことにしてW

404:y
08/07/15 21:20:07
>>398

以下のコードを実装して、GetRangeを実行してみてください。
"セルを選んでください"が表示された直後に限り、
SelectionChangeイベントプロシージャの3行目以降が実行され、
さらにそこから"次の処理"プロシージャが呼ばれます。

■Module1
Public evFlag As Boolean
Public selectedRange As Range

Public Sub GetRange()
MsgBox "セルを選んでください"
evFlag = True
End Sub

Public Sub 次の処理()
MsgBox selectedRange.Address & "が選ばれました"
End Sub

■Sheet1
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If evFlag = False Then Exit Sub
Set selectedRange = Target
evFlag = False
Call 次の処理
End Sub

405:デフォルトの名無しさん
08/07/15 21:25:23
>>398
メッセージの表示と入力を分ける必要はあるの?

これじゃダメなのか?
Sub セル選択()
Dim X As Range

On Error Resume Next
Set X = Application.InputBox(Prompt:="セルを選択して下さい", Title:="セルの選択", Type:=8)
On Error GoTo 0
If Not X Is Nothing Then
MsgBox "選択したセルは " & X.Address
Else
MsgBox "キャンセルしたよ"
End If
End Sub



406:デフォルトの名無しさん
08/07/15 21:28:08
>>399
そもそもVBEのカラー定義は貧弱だから
その辺が強力かつ表示通りにカラー印刷出来るテキストエディタ使った方がいい

407:y
08/07/15 21:31:21
>>398

念のためにまた書きますが、InputBoxメソッドを使った方が
はるかに簡単です。ほぼ同じことが以下の5行でできます。
しかも、他シートのRangeも取得可能です。

Public Sub GetRange2()
Dim selectedRange As Range
Set selectedRange = Application.InputBox("セルを選んでください", Type:=8)
MsgBox selectedRange.Address & "が選ばれました"
End Sub

>>404の利点は、セルが選ばれた瞬間に次の処理を発動させられる
点ぐらいです。(上の例はOKボタンを押す必要があります)


408:y
08/07/15 21:32:34
>>405
あ、かぶっちゃった。

409:デフォルトの名無しさん
08/07/15 21:34:37
Addressをデバッグ画面やmsgboxに表示させるときは
Address(0, 0)とした方が解りやすいぞ
習慣にしておこう

410:401
08/07/15 21:47:30
>402
>403
ドンマイ w
でも、ありがとうございます。

どなたか、わかる方いらっしゃいますか?

411:353
08/07/15 21:56:21
並び替えのことで質問したものですが
結局シリアル値での日付列を追加して無事処理できました。
いろいろとありがとうございますorz


412:y
08/07/15 22:51:16
>>410

■初心者向け

Public Sub Del1()
Dim tmp As Range
For Each tmp In Range("A:B")
If tmp.Value <> "" Then
If tmp.Value <> 0 Then
Exit Sub
End If
End If
Next
Range("1:50").Delete
End Sub

413:デフォルトの名無しさん
08/07/15 23:00:52
>>410
なんか質問がおかしいように思うよ。
>>412さんの構文の通り、セルに名前を付けてあるの?
名前を付けたセルの値が・・・って事なら構わないんだけど、
何か勘違いしてるかな。

A:B列の、どのセルを対象にしたいの?範囲は無し?
A列かB列の任意のセルに0か空欄があった場合、1行目から50行目までを削除するの?


414:デフォルトの名無しさん
08/07/15 23:35:23
VB6で質問があるのですが
セルの値が分数で記述されているのを
隣のシートに小数点表記で表示させる方法ってありますか?

隣のシートには表示出来るのですが、小数点にならなくて

415:y
08/07/15 23:59:33
>>410

■玄人向け(処理が速い)

Public Sub Del2()
Dim rg As Range, tmp As Range
With Range("A:B")
On Error GoTo err1
Set rg = .SpecialCells(xlCellTypeFormulas)
For Each tmp In rg
If tmp <> 0 Then Exit Sub
Next
err1:
On Error GoTo 0
On Error GoTo err2
Set rg = .SpecialCells(xlCellTypeConstants)
For Each tmp In rg
If tmp <> 0 Then Exit Sub
Next
err2:
Range("1:50").Delete
End With
End Sub
--------
>>413
たぶん>>410さんは、A:B列の「すべての」セルが0または""なら
1:50行を削除したい、という意図だろうと受け取っています。
ちなみに>>412では、名前は使っていないつもりですが、
どの部分のことですか?

416:y
08/07/16 00:12:24
>>414

小数点表記させたいセルの書式を"標準"または"数値"にしてください。
"数値"にした場合は、小数点以下何桁まで表示させるかを指定してください。

VBAで処理したい場合は、NumberFormatプロパティで操作できます。
それをキーワードに検索してみてください。

417:デフォルトの名無しさん
08/07/16 00:39:04
>>410
WorksheetFunctionを使った場合もどうぞ

Sub 削除()
With Application.WorksheetFunction
If (.CountIf(Range("A1:B50"), 0) <> 0) Or (.CountIf(Range("A1:B50"), "") <> 0) Then
Range("1:50").Delete
End If
End With
End Sub

だけど範囲がAB列全部てどうなのさww
いや、AB列全部に0もしくは空白が無いならいいけどさ

End(xlUp)とかを使ってデータの最終行を取得するとかをした方が
いいんじゃない?

418:デフォルトの名無しさん
08/07/16 00:57:59
もう1つFindを使った場合もどうぞ

Sub 削除2()
Dim X(1) As Variant
With Range("A1:B50")
Set X(0) = .Find(0)
Set X(1) = .Find("")
If Not (X(0) Is Nothing) Or Not (X(1) Is Nothing) Then
Range("1:50").Delete
End If
End With
End Sub

あと、テストするのに範囲をA1:B50に指定してるから

419:デフォルトの名無しさん
08/07/16 01:31:40
>>401

念のため補足しておくと、

>>412, >>415は、範囲内のすべてのセルの値が(空白または0)なら削除を行う処理
>>417-418は、範囲内に(空白または0)のセルが1個でも含まれていたら削除を行う処理

をアドバイスしている。
これは>>410の質問の仕方が曖昧だから。

420:y
08/07/16 02:43:27
>>394

StDev関数は、Rangeオブジェクトだけでなく、配列変数も引数として
受け取ることができます。次のコードを試してみてください。

Sub t()
Dim args As Variant
args = Array(1, 2, 3, 4, 5)
Debug.Print WorksheetFunction.StDev(args)
End Sub

つまり、各シートに散らばっている数値を、いったん
配列変数にまとめ、配列ごとStDev関数に渡すやり方が可能です。
(Unionでやろうとしたことと考え方は同じです)

421:デフォルトの名無しさん
08/07/16 08:27:19
確かに、慣れてない奴にウェブで調べさせた怪しげな標準偏差関数を自作させるよりは、
>420の方が余程まともだな。

422:410
08/07/16 13:36:35
>412,415,417,418

丁寧にありがとうございます。

すみません説明不足でした。
A列かB列の任意のセルに0か空欄があった場合、
【0か空欄がある行だけ抜き出して削除する】処理がしたいのです。

412,415,417,418を試しにやってみましたが、
1~50行全て消えてしまったので、これだとちょっとマズいんです。(笑)

誠にお手数かけますが、ご教授頂けますでしょうか
お願い致します。



423:デフォルトの名無しさん
08/07/16 14:04:58
>>422
少しは自分で考えよう
>>1★5


>>その他
踊らされてなんでもホイホイ答えずに
多少は質問者にも頭使わせよう

424:デフォルトの名無しさん
08/07/16 14:12:14
Findのヘルプを読んでみ

425:デフォルトの名無しさん
08/07/16 14:14:47
>>422

えーーーー

>VBA初心者の者ですが、
>(A:B)列のセルがゼロか空白ならば、
>(1:50)の行が削除される構文をどなたか教えて頂けますか。

どう読み取っても50行目まで全部削除したい主旨じゃん・・
ちゃんと質問してくれよ

まあ答え解らないけどwwwwwww


426:デフォルトの名無しさん
08/07/16 14:21:45
VBAの前に日本語だな

427:デフォルトの名無しさん
08/07/16 14:59:51
Sub sakujo()
Dim i
Dim j
Dim q
j = Cells(Rows.Count, 1).End(xlUp).Row
i = 1
Do Until q > j
If Cells(i, 1).Value = "" Or Cells(i, 1).Value = "0" Or Cells(i, 2).Value = "" Or Cells(i, 2).Value = "0" Then
Rows(i).Select
Selection.Delete Shift:=xlToLeft
q = q + 1
Else
q = q + 1
i = i + 1
End If
Loop

あえて解説はしない。

428:デフォルトの名無しさん
08/07/16 15:00:53
Sub hoge()
Dim i
Dim j
Dim q
j = Cells(Rows.Count, 1).End(xlUp).Row
i = 1
Do Until q > j
If Cells(i, 1).Value = "" Or Cells(i, 1).Value = "0" Or Cells(i, 2).Value = "" Or Cells(i, 2).Value = "0" Then
Rows(i).Delete
q = q + 1
Else
q = q + 1
i = i + 1
End If
Loop
End Sub

で・・・。何やっとんだワシ・・・。

429:デフォルトの名無しさん
08/07/16 16:16:15
>>428
うまくいってないよ

430:410
08/07/16 16:22:47
うわ・・・皆様本当にご迷惑おかけして
申し訳ないです。

>427・428
ありがとうございます。
でも、やってみましたが、削除できてないっす。

難しいですね・・・

431:デフォルトの名無しさん
08/07/16 16:30:34
>>410
>412,415,417,418を試しにやってみましたが、
>1~50行全て消えてしまったので、これだとちょっとマズいんです。(笑)

当たり前でしょ、最初の質問がそういう条件だったんだから

取りあえず、Findを使った場合の処理

Sub 削除3a()
Call 削除3b(0)
Call 削除3b("")
End Sub

Sub 削除3b(FD As Variant)
Dim X As Variant, XAddr As Variant
Dim XS As String

With Range("A1:B50")
Do
Set X = .Find(What:=FD, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte:=False)
If Not X Is Nothing Then
Range(X.Row & ":" & X.Row).Delete
End If
Loop Until X Is Nothing
End With
End Sub


432:410
08/07/16 16:43:07
>431
ありがとうございます。
空白だけの行は削除されました!
でも0が入ったセルの行は削除されませんでした。


433:428
08/07/16 16:43:13
あれ?動かないですか?
A列とB列を判定してhitしたらその行消してるだけなんだけど。

434:デフォルトの名無しさん
08/07/16 16:45:07
教えてください。エクセル2007でV-nasCADの画像を貼り付けて印刷したら
印刷があれるのですが、どうしたらいいでしょうか?
2002の時はきれいにでていたのですが・
だれか教えてください。

435:431
08/07/16 16:52:21
>>410
指定範囲はあっている?
俺の書いたコードはA1:B50までの範囲しか対象にしていないよ

もしくは引数の指定が正しくできてる?

436:410
08/07/16 17:08:12
合ってますが、やはり0が入ったセルの行が削除されません。

Range(X.Row & ":" & X.Row).Delete

この部分に"0"を入れなければならないのでは?

437:デフォルトの名無しさん
08/07/16 17:14:08
じゃあ入れて試してみろやボケ

438:431
08/07/16 17:22:36
>>410

取りあえずコードの説明しとくよ

Sub 削除3a()
' 削除3bプロシージャの呼び出し
Call 削除3b(0) ' ←セルの値0を削除(引数として0をセット)
Call 削除3b("") ' ←空白セルを削除(引数として""(空白)をセット)
End Sub

Sub 削除3b(FD As Variant)
Dim X As Variant, XAddr As Variant
Dim XS As String

With Range("A1:B50") ' セル範囲"A1:B50"を指定
Do
' ↓引数FDに指定された値のあるセルを検索
' セルがあった場合はそのRangeオブジェクトを変数Xにセット
Set X = .Find(What:=FD, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte:=False)

' ↓Rangeオブジェクトの取得がされていない場合は処理をしない
If Not X Is Nothing Then
'指定されたセルの行番号のセルを削除
Range(X.Row & ":" & X.Row).Delete
End If
Loop Until X Is Nothing 'Rangeオブジェクトの取得がされていない場合はLoopを抜ける
End With
End Sub


439:デフォルトの名無しさん
08/07/16 17:33:03
Sub test()

Range(401).Delete

End Sub

440:デフォルトの名無しさん
08/07/16 18:47:10
>>401
今いちど、何をしたいのかを日本語で誰にでもわかるように書いてみれ。


441:デフォルトの名無しさん
08/07/16 18:54:42
>>428
"0"だと文字列。数値の0の判定を追加しないといかん。

442:デフォルトの名無しさん
08/07/16 19:54:03
Cells(a,b)が、とあるRange(Unionであっちこっちくっつけてる)の中に含まれているかどうかを返す関数ってあります?

443:デフォルトの名無しさん
08/07/16 20:58:59
>>442
なかったらこれ使えるかな?

Function included(ByVal maybeSubset As Range, ByVal maybeSuperset As Range) As Boolean
included = maybeSubset.Count = Application.Intersect(maybeSubset, maybeSuperset).Count
End Function

444:y
08/07/16 21:04:40
>>422

【0か空欄がある行だけ抜き出して削除する】処理、ということであれば、
AutoFilterが便利です。

Sub Del3()
Range("1:1").Insert
With Range("A1:B51")
.AutoFilter field:=1, Criteria1:="=", Operator:=xlOr, Criteria2:="0"
Range("A2:B51").SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilter field:=2, Criteria1:="=", Operator:=xlOr, Criteria2:="0"
Range("A2:B51").SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ActiveSheet.AutoFilterMode = False
Range("1:1").Delete
End Sub

0または空白の行だけを表示させ、表示されている行だけを削除する、
という処理を、A列とB列に順番に行っています。
1行目に新しい行を挿入し、最後に消しているのは、AutoFilterを使うために
見出し行が必要だからです。


>>442
Intersect関数を使ってみてください。
複数のセル範囲の共有範囲を返す関数です。
共有範囲が返らなかったら、「含まれていない」と判断できます。

445:y
08/07/16 21:10:09
あ、既に>>443で答えが出てましたね。


446:442
08/07/16 21:13:48
>>443,444
ありがとうございます、無事にできました。

447:デフォルトの名無しさん
08/07/16 21:43:24


   うぜーよ




448:デフォルトの名無しさん
08/07/17 00:25:04
何がだ

449:394
08/07/17 02:38:11
レス頂きありがとうございます。

>>395
StDev無しで普通に計算する方法も考えましたが、もっと効率的な方法はないものかと思い質問させて頂きました。

>>420
配列が使えるというのは初めて知りました。
その方法で試してみたいと思います。

450:デフォルトの名無しさん
08/07/17 10:23:40
>>398
亀だがこんなのもできる一応

Public waiting_selection_change As Byte
Function user_selected_range() As Range
waiting_selection_change = 1
MsgBox "セルを選択して下さい"
While waiting_selection_change = 1
DoEvents
Wend
Set user_selected_range = Selection
End Function

Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
If waiting_selection_change = 1 Then waiting_selection_change = 0
End Sub

451:デフォルトの名無しさん
08/07/17 11:45:20
生徒の試験の点数を降順(100、97、90・・・)に並べてある
A列の隣(B列)に1、2、3と順位をつけて、尚且つ、
A列の空白になっているセルには順位をつけないようにするには、
どうしたらいいでしょうか。ご教授お願い致します。

452:451
08/07/17 12:07:20
すみません

>A列の空白になっているセルには順位をつけないようにする
→B列のセルを空白のままにするには

でお願い致します。

453:デフォルトの名無しさん
08/07/17 12:56:37
もう1つ列を作って呼び出さないようにする。

454:デフォルトの名無しさん
08/07/17 14:11:48
Sub junni()
Dim i
Dim j
j = 1
For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row
If Cells(i, 1) <> "" Then
Cells(i, 2) = j
j = j + 1
End If
Next i
End Sub


455:デフォルトの名無しさん
08/07/17 17:38:27
検索についてお聞きしたいのですが、
シート全体を対象に検索する場合はCellsで可能なんですが、
特定のセル範囲を検索する場合ってどうやればよいでしょうか?

例えばA1:C10の範囲内のセルだけ"パソコン"という文字列を検索するにはどうすればよいでしょうか。

456:デフォルトの名無しさん
08/07/17 19:00:44
cellsは全セル対象でおk。

指定範囲は、
Range("A1:C10").Find(What:="パソコン").Activate
こんな感じ。
マッチした後の処理が書いてないから、マッチしたセルをactive。

457:デフォルトの名無しさん
08/07/17 19:27:38
>>456
なるほど。
What;= が必用だったのか・・
ありがとう。

458:デフォルトの名無しさん
08/07/17 23:24:35
>>457
セミコロン(;)じゃなくて、コロン(:)だよ

あと、「What:=」見たいに使うのを名前付き引数といって
指定()内に記述する順番がばらばらでも大丈夫な引数指定の事

省略した場合はFindの場合(What:=, LookIn:=, LookAt:= …)の順に引数を指定したとみなされる


459:デフォルトの名無しさん
08/07/18 00:30:09
かなりなスレ違いお許し下さい

過去の株価をVBAで検証したいのですがスキル不足です。
検証の内容は、ごく単純なもので恐らく数十分ほどで組めるのではないかと思われます。
(検証条件=システムは、恥ずかしい位、幼稚なものです。期待なさらないで下さい。
特別な秘密など有したものではありません・・)

どなたか有償でVBAを組んで頂けませんでしょうか。
報酬は、先払い3000円・完成後3000円の合計6000円を考えています。
指定口座に迅速にお振込み致します。

二か月分の株価を載せたエクセルデータと
検証条件を説明したテキストファイルを作りました。
これをメールでお送りします。
請け負って頂けるか否か、報酬は上記金額で良いか
とりあえずお見積もりして頂ける方メール下さい。
どうぞ宜しくお願い致します。

460:デフォルトの名無しさん
08/07/18 01:04:58
>>459
口座無いからタダでやりたい

461:459
08/07/18 01:10:20
>>460
書留ででもお送りしますよ^^
そうゆうのもお嫌でしたら無償でもいいですがw
よかったらメール下さい

462:デフォルトの名無しさん
08/07/18 01:13:14
商品コード 数量 商品名 単価 合計
このような列の集まりで、
商品行が増えていくシートで、発注表を作っています。

数量は普段空白で、注文するときに数量を入れて、
数量がない行は削除(上にシフト)して、プリントアウトしています。
最終的に「数量が空白」を全部消してからプリントになります。

で、これをマクロにすると
数量(一番初めの商品は3行目なのでB3セル)が書いていなければ行削除、
数量が書いてあった場合は何もせずに下の行へ。

で、最後に識別文字の「★」であれば、終了ということをやりたいです。
マクロで観てみると

Rows("3:3").Select
Selection.Delete Shift:=xlUp

このように出ました。
3行目を削除して上にシフトしています。

463:462
08/07/18 01:14:20
if(現在のセルが★が入っていなければ)
{
  if(現在のセルが空でなければ)
  {
   その行を選択して
   削除(上にシフト)
  }else
  セルを下に移動
}
 プリントアウト

 こんな感じで脳内ではできたのですが、コード化は無理ぽですorz
 どう書けばいいでしょうか?

464:459
08/07/18 01:23:30
>>461
メール送りました。
とりあえず内容見て考えさせてください。

465:デフォルトの名無しさん
08/07/18 01:26:36
>>462
このスレの410宛てのレスを読め

大体似たような処理で出来る

466:デフォルトの名無しさん
08/07/18 01:33:50
>>463
Sub hoge()
Dim startCell As Range
Set startCell = [C4] ' 商品コードの値が始まるセル
Dim i%
While startCell.Offset(i) <> "★"
With startCell.Offset(i)
If .Offset(, 1) = "" Then
.EntireRow.Delete
Else
i = i + 1
End If
End With
Wend
End Sub


467:459
08/07/18 01:36:30
>>464
ありがとうございました
本メールから今、送信しました
ご検討宜しくお願い致します

468:459
08/07/18 01:37:56
>>467
了解です^o^
今みてます

469:デフォルトの名無しさん
08/07/18 09:05:13
香ばしいこと行われているようですねw

470:デフォルトの名無しさん
08/07/18 16:09:08
worksheetsを追加した際に
そのシートにWorksheet_Activate()
も追加したいのですが、どのように指定すればできるのでしょうか?

471:デフォルトの名無しさん
08/07/18 17:05:33
普通にやればいいじゃん

472:470
08/07/18 17:21:42

worksheets.add after:=activesheet
で新しいシートを追加するマクロがあるのですが、worksheets.????みたいな感じでなにかできる方法があるのでしょうか?
マクロで追加したシートにマクロを記述する関数などありましたら教えていただきたいです。

473:デフォルトの名無しさん
08/07/18 17:33:49
だから、「VBAを使ってVBAコードを記述する」方法を普通にやればいいだけだってば
検索すればいくらでも情報は出てくる

474:470
08/07/18 18:28:56
ありがとうございます。
検索したら
With ThisWorkbook.VBProject.VBComponents.Item("Sheet2").CodeModule
.InsertLines 1, "書きたいコード"
End With
でできるみたいですね。
ありがとうございます。

475:デフォルトの名無しさん
08/07/18 20:05:09
本当にやりたい目的と、今とろうとしている手段が乖離している気がするが、まあいいや

476:デフォルトの名無しさん
08/07/18 20:08:16
>>472

hoge = activesheet.index
worksheets.add after:=activesheet
sheets(hoge+1).activate

じゃダメ?

477:デフォルトの名無しさん
08/07/18 20:21:01
>>476
アクティベイトしたいんじゃなくて、ハンドラを入れたいんでしょ。

478:デフォルトの名無しさん
08/07/18 20:54:15
>>470
普通に標準モジュールにコードを書けばいいんじゃねーの?

イベントハンドラが使うならクラスモジュールを使えばいいし

479:デフォルトの名無しさん
08/07/18 23:51:10
ExcelVBAを扱うExcelVBAコードはないのか!

480:463
08/07/19 02:28:06
>>466
| Dim startCell As Range
| Set startCell = [C4] ' 商品コードの値が始まるセル

発注書:日付
商品コード 数量 商品名 単価 合計
001      1   hoge  3,000 3,000
002         hoge  1,500 
003      1   hoge  2,000 2,000
004         hoge  4,000 
        ★
こんな感じなので、商品コードはA3になります。
ここをA3に変更して実行したところループになりました。
今回は★は[B7]ですね。

| Dim i%
ここの「%」の意味がわかりませんでした。
先述のAs Rangeはオブジェクトということはわかりました。

| While startCell.Offset(i) <> "★"
 [A3]のi行下が★でなければということで、★の位置をA7にしたらループが止まりました。

| With startCell.Offset(i)
| If .Offset(, 1) = "" Then
 i行オフセットした右隣が""の場合

| .EntireRow.Delete
 その行を削除

| Wend
While ... Wendという使い方、御教示ありがとうございます。
 とても勉強になりました。

481:463
08/07/19 02:33:17
すいません、どうしても気になることが・・

| Dim i%
| While startCell.Offset(i) <> "★"
| With startCell.Offset(i)

特に i = 1
と変数に入れていないのですが、なぜiが1を入れたような挙動を
取るのでしょうか?
i% に何かしらそういう意味があるのでしょうか?

482:463
08/07/19 02:47:44
>>466
startCell の数量[B3]に数値があれば、完璧に動作をするのですが、
この数量[B3]に数値がなければ、
・startCell行の数量が空(★ではない)ので、行を削除
してWendからwhile行を実行しようとした瞬間に

実行時エラー:424
オブジェクトが必要です
と出てストップします。

While startCell.Offset(i) <> "★"
ここで止まってしまうのですが、1回目は行削除できるのに、
なぜか2回目の処理で止まってしまうのが、よくわかりません・・・。

483:デフォルトの名無しさん
08/07/19 03:16:19
>>463

>Dim i% ← これは、変数iを整数型で宣言している
%が整数型の型宣言文字

>特に i = 1
>と変数に入れていないのですが、なぜiが1を入れたような挙動を
>取るのでしょうか?

これについては
↓のIfで空白なら行を削除、空白で無いなら i に+1している
If .Offset(, 1) = "" Then
 .EntireRow.Delete
Else
 i = i + 1
End If

>実行時エラー:424
>オブジェクトが必要です
>と出てストップします。

これについては
Set startCell = [C4] でstartCellにRangeオブジェクトをセットしているのに
そのセルを削除してしまったので、セットしたRangeオブジェクトがねーよwwとExcelが言ってるだけ

基本的に削除するセルを基準にしちゃだめだろ




484:デフォルトの名無しさん
08/07/19 03:55:10
>>463
あとWhile ... Wendという使い方もあるけど
普通はDo~Loopを使うよ

Do~Loopを使う場合はこんな感じ

Sub ★まで削除()
 Dim TCell As Range
 Dim iX As Integer

 Set TCell = Range("B2") ' ★のある列のタイトル部分(商品コードとか数量と書いてあるセル)
 iX = 1
 Do Until TCell.Offset(iX, 0).Value = "★"
  With TCell.Offset(iX, 0)
   If .Value = "" Then
    .EntireRow.Delete xlShiftUp
   Else
    iX = iX + 1
   End If
  End With
 Loop
End Sub

485:デフォルトの名無しさん
08/07/19 04:05:48
Do...LoopがあるからWhile ... Wendなんていらね、使った事もない。
While ... Wendなんて使うとコードが汚れるとさえ思える。

486:デフォルトの名無しさん
08/07/19 09:42:09
へー

487:y
08/07/19 10:27:10
>>484
元の質問とは関係ないですが、コードがインデント付きで表示されて
いるのでびっくりしました。しかも、VBAEditorが全角スペースを自動的に
半角スペースに変換してくれることを初めて知りました。
>>484をそのまま貼り付けるとエラーになると思い込んでた)

これはVBAEditorの仕様でしょうか?
それとも「全角空白は半角に変換する」みたいなオプションが
どこかにあるのですか?



488:デフォルトの名無しさん
08/07/19 10:51:13
VBAEditorではなくVBEditor(Visual Basic Editor/VBE)ですよ
例えEditする対象がVBAでもね

で、これはオプションではなく固定仕様、VBEのと言うよりはMS製IDEの仕様だけどな
まあMS製以外でもこの機能を有するIDEはあるし
テキストエディタでもマクロや正規表現定型置換を用意しておけば一発だけど

因みに、一応半角スペースでインデントすることも出来ますよ

Do Until TCell.Offset(iX, 0).Value = "★"
With TCell.Offset(iX, 0)

ブラウザに因っては正しく表示&コピー出来ない場合もあるけど

489:デフォルトの名無しさん
08/07/19 10:54:26
因みに↑はJaneとかの専ブラ向けね
確かIE向けは↓かな

    Do Until TCell.Offset(iX, 0).Value = "★"
        With TCell.Offset(iX, 0)

490:y
08/07/19 11:19:34
>>488 ありがとうございます。私も試しに...

Sub test()
 With Range(Range("a2"), Range("b:b").Find("★").Offset(-1)).EntireRow
  .AutoFilter field:=2, Criteria1:="="
  .Offset(1).SpecialCells(xlCellTypeVisible).Delete
  .AutoFilter
 End With
End Sub

(コードは>>463の別解。★の行も含めて消えますが)

491:デフォルトの名無しさん
08/07/19 11:21:48
うぜーよ

492:デフォルトの名無しさん
08/07/19 12:03:41
>>485
他の言語からやってきたものからすると、
While ~ Wendの方がとっつきやすいんだよ。
単なるキーワードの違いだがな。
ただ、While ~ Wendだとループの脱出が…

493:485
08/07/19 18:43:46
やっぱりそうだよな、他の言語やってるとそうなんだけどね。
でもVBではDo...Loopに限るよ、Do...Loopの仕様は反復制御として完璧だからね。

494:デフォルトの名無しさん
08/07/19 22:06:59
uze-yo

495:デフォルトの名無しさん
08/07/19 22:27:37
心の狭い子…

496:デフォルトの名無しさん
08/07/19 23:01:26
こんばんは。VBE初心者のものです。

講義の宿題で7×7の魔方陣をVBEで解いてこいといわれました。
しかしながら自分のスキルでは動にもなりませんでした。

自分はIFやDim等までしか習っていませんがそれで解ける方法があったら
誰か助けてください。




497:デフォルトの名無しさん
08/07/19 23:06:32
ループで全通り回せばいいだけじゃん

498:デフォルトの名無しさん
08/07/19 23:18:58
・中央は25
・1列の合計は(1+25)*25/5で130


499:デフォルトの名無しさん
08/07/19 23:28:59
>>498
???
25x7=175

500:デフォルトの名無しさん
08/07/19 23:37:58
ちがったか
1から25の合計は(1+25)*25/2=325
1列の合計はこれを5で割るから65だな

501:デフォルトの名無しさん
08/07/20 00:23:45
最上段中央に1を配置したら、右上に移動しながら2,3,4と次の数値をと入れていき、7の倍数時は右上ではなく下へ移動

上下、左右がループしてるとして(つまり1行目の上は7行目、7列目の右は1列目)この処理を続ければあっという間に完成

奇数の場合は上記の法則が使えるので超簡単
因みに7*7の場合は(1+7^2)/2*7で175が1列の合計
コードはForと算術演算(数値計算)が使えれば条件分岐(IF)すら要らない簡素なもの
小学生あたりにはオススメの問題だ

502:デフォルトの名無しさん
08/07/20 00:26:27
>>501
複数の解(回転・鏡像を除く)が存在する場合も無視?

503:デフォルトの名無しさん
08/07/20 00:30:01
無視って何を?

504:デフォルトの名無しさん
08/07/20 02:27:42
どうやったら条件分岐使わずに書けるのかわからん
その小学生にお勧めのコードをお教えくださいませ

505:デフォルトの名無しさん
08/07/20 02:30:27
あと、開始座標がどこでも結果同じだろ。
マ板とは思えんなここ

506:デフォルトの名無しさん
08/07/20 05:45:41
別に501が唯一の解法だなんて書いてないし、
解法の一つとしては間違ってないわけだが、この子は何が気に入らないんだろう?
何か勘違いしてるのかな?

507:デフォルトの名無しさん
08/07/20 06:45:52
ちょっと書くだけで過剰反応するバカがいるから面白がってるだけ

508:デフォルトの名無しさん
08/07/20 08:30:49
>>501にからんでるやつ頭悪そう。
魔方陣には特殊な解があるぞという回答に対して他の解は無視かよだなんてスジ違いのイチャモン。
頭が悪いんだろうな。

509:デフォルトの名無しさん
08/07/20 08:35:53
ごめん。魔方陣って何?
面白そうなのに全然話に参加できないんだけど。

って人が多いと思う・・・俺含め。(俺だけ?)

510:デフォルトの名無しさん
08/07/20 08:39:54
魔方陣を知らない人は少ないと思う。
君は少数派。

511:デフォルトの名無しさん
08/07/20 09:22:18
ググれカス

512:デフォルトの名無しさん
08/07/20 10:33:05
寧ろwikiれ

513:デフォルトの名無しさん
08/07/20 11:00:50
>>505
マ板じゃないからな・・・

514:y
08/07/20 11:05:25
>>509ではないですが、私も魔方陣のことはあまり知らなかったので、
性質を調べてマクロを組んでみました。非常に面白いです。
どうせやるなら、n * n の魔方陣のすべての解を列挙できるように
しようと思い、基本的に>>497の総当り方式でやってますが、かなり浅はかでした。

3*3は1秒ぐらいですべての解(8通りでOK?)が求まるのですが、
4*4は今の調子だと4~5時間はかかりそうです(現在バックグラウンドで計算中)。
あるサイトによると6*6で約1800京通りあるらしく、7*7のすべての解など
到底無理なんだと理解。自己満足な知識がまた1つ増えました。

全然アドバイスになっていませんが、>>496の宿題で求められているのは、
要するに>>501で紹介されているようなオーソドックスな解法をVBAで
シミュレーションせよ、ということなんでしょうね。

515:デフォルトの名無しさん
08/07/20 11:05:28
魔法も使えないって
おまえら30年間何してきたんだよ

516:デフォルトの名無しさん
08/07/20 11:33:30
魔 *方* 陣

517:y
08/07/20 11:41:12
話題ついでに、質問させてください。

>>514で触れた「総当り方式」を実現するために、1 から n^2 までのn^2個の配列に、
すべての順列組み合わせを生成する再帰プロシージャを書きました。

これまで再帰処理はめったに使う機会がなかったので、今ちょうど気になっているのですが、
VBAの仕様としては、関数の多重呼び出しはどのくらいの深さまで許容されているのでしょうか。
MSDNには「多重呼び出しをやりすぎるとStackOverflowExceptionになりますよ」とあるのですが、
それ以上の情報は見つけられませんでした。(環境依存でしょうか?)


518:y
08/07/20 11:44:32
(修正します)
「1 から n^2 までのn^2個の配列に、」
   ↓
「1 から n^2 までのn^2個の配列について、」


519:デフォルトの名無しさん
08/07/20 13:41:30
試してみた(Excel2000)

Function test(i)
test = test(i + 1)
End Function

test 1でエラーが出たところでiは4227だったよ
ちなみに
Function test(i As Integer) As Integer
とすると6453

Function test(i, j)
test = test(i + 1, j + 1)
End Function
では3453

深さの問題じゃないね

520:デフォルトの名無しさん
08/07/20 13:52:31
講釈ばっかで回答が一つも無い件

521:デフォルトの名無しさん
08/07/20 14:11:33
Sub 魔方陣()

range("A1") = "7×7の魔方陣"

End Sub


できたよ~

522:デフォルトの名無しさん
08/07/20 15:50:04
Wikipediaの記述どおりつくってみたつもりだが… 5,9,13…がうまくいかない
URLリンク(ja.wikipedia.org)
Const size = 15
Sub 魔方陣()
Cells.Clear
If size Mod 2 = 0 Then End
Dim i%, x%, y%
x = size / 2 + 1
y = 1
For i = 1 To size * size
Cells(y, x) = i
y = y - 1
x = x + 1
補正 x, y, i
Next i
End Sub

Sub 補正(ByRef x%, ByRef y%, ByVal i%)
y = (size + y) Mod size
x = (size + x) Mod size
If y = 0 Then y = size
If x = 0 Then x = size
If Cells(y, x) <> "" Then
y = y + 2
x = x - 1
If i < size * size Then
補正 x, y, i
End If
End If
End Sub

523:デフォルトの名無しさん
08/07/20 16:05:58
よくわからんが
size / 2 + 1

524:デフォルトの名無しさん
08/07/20 16:07:13
を、
(size + 1) / 2
にするだけなんじゃ?

525:522
08/07/20 16:11:11
>>523-524
わwそんな罠があるとはw削られるもんだと思ってたw
ありがとう

526:デフォルトの名無しさん
08/07/20 16:23:12
それが原因なら5,9,13だけでなく3,7、11もうまくいかんだろ

527:522
08/07/20 16:27:35
>>526
うまくいくみたい
3 / 2 + 1 => 2
5 / 2 + 1 => 4
7 / 2 + 1 => 4
9 / 2 + 1 => 6
11 / 2 + 1 => 6
13 / 2 + 1 => 8
15 / 2 + 1 => 8
17 / 2 + 1 => 10
19 / 2 + 1 => 10
21 / 2 + 1 => 12
23 / 2 + 1 => 12
25 / 2 + 1 => 14

528:デフォルトの名無しさん
08/07/20 16:35:07
所謂ISO丸めだね。小数点以下一桁を丸める場合、その桁が5のときは偶数になるように丸める。
四捨五入とは違うから要注意だ。

529:デフォルトの名無しさん
08/07/20 17:39:48
>>517
nestingは10じゃなかったっけ。

530:デフォルトの名無しさん
08/07/20 18:13:01
ま、>>496はマルチだしな


531:デフォルトの名無しさん
08/07/21 14:00:09
すみません、よくわからないので教えてください(excel2003)

1つのセルの中にALT+Enterで改行を入れ、複数項目を入れた場合
項目1つ1つを取り出すにはどうしたらよいのでしょうか?

tmp = Split(ActiveSheet.Range("A1").Value, "\n")
For i = 0 To UBound(tmp)
MsgBox tmp(i)
Next i

というようなコードを書いたのですが、すべて取得してしまいます
\nを\r、\r\nに変えても駄目でした

532:デフォルトの名無しさん
08/07/21 14:20:45
そりゃそうだ
そのコードだと"\n"って文字で分割してるのであって改行コードで分割してるわけじゃないからな
VB、VBAの改行は、組込定数のvbCr、vbLf、vbCrLf、vbNewLineやChr(13)、Chr(10)であって
断じて\n、\r、\r\nでは無い

勝手に\n、\r、\r\nが使えることにするな
MsgBoxやDebug.Printで"a\r\nb"でも出力してみればわかることだろ
なんで最低限の確認も出来ないかなぁ?

ただコードを書くだけなら小学生でも出来るが、問題が起きたときに最低限のデバッグが出来ないと
VBA使えるとはとても言えないぞ

533:デフォルトの名無しさん
08/07/21 14:35:02
>VBA使えるとはとても言えないぞ
VBA使えなくてもお前ら使えばいいだけだしなw

534:デフォルトの名無しさん
08/07/21 14:41:34
>>531
regexpを使うと良いよ。正規表現。
パターンは ".*?\n" で行けるかな。

executeでコレクションに格納してから for each in で項目引っこ抜いても良いし、
submatchで引っこ抜いても行けると思うよ。


535:デフォルトの名無しさん
08/07/21 14:42:25
セル内改行が \n で取得出来るか、ちょっと試してくるね。

536:デフォルトの名無しさん
08/07/21 14:53:15
Sub 正規表現()
Dim hoge, strpat As String, hogeMatch
Set hoge = CreateObject("VBScript.RegExp")
strpat = ".*?(\n|$)"
With hoge
.Pattern = strpat
.IgnoreCase = True
.Global = True
End With
Set hogeMatch = hoge.Execute(Cells(1, 1))
If hogeMatch.Count > 0 Then
Debug.Print (hogeMatch(0))
Debug.Print (hogeMatch(1))
Debug.Print (hogeMatch(2))
End If
End Sub

こんな感じで取得は出来たよ。
submatchはあまり詳しく無いんで分かりません。
取り出した文字列には、改行文字も含まれてるので、
取り出した後に replace で vblf を "" に置き換えて除去すると良いかもね。

537:デフォルトの名無しさん
08/07/21 14:54:51
あ、取り出される要素数がその都度違うようだったら、
hogeMatch.countの回数だけ繰り返してね。

538:デフォルトの名無しさん
08/07/21 14:57:35
ああ・・・ vblf で split するのが一番良かったかもしれませんね・・・。
スレ汚しすいませんでした。

Sub piyo()
Dim hoge
hoge = Split(Cells(1, 1), vbLf)
Debug.Print (hoge(0))
End Sub

ごめんなさい。

539:デフォルトの名無しさん
08/07/21 16:00:42
>>536
改行コードがLF固定だったら、
MultiLine = True, Global = Trueにした上で
"^.*"でやれば無駄な改行コードも取れずにそのまんますんなり行ける。

540:デフォルトの名無しさん
08/07/21 17:04:38
ああ、multilineでセル内改行取れましたね・・・。勉強になります。

541:デフォルトの名無しさん
08/07/21 18:46:02
行分割するだけなのに、何故に外部コンポ引っ張り出して正規表現使う必要が・・・・・

542:デフォルトの名無しさん
08/07/21 19:52:55
そう言う年頃なんだろよ。

543:デフォルトの名無しさん
08/07/21 23:33:06
頭でっかち

544:y
08/07/22 00:41:47
>>519
ありがとうございます。
うちはExcel2003ですが、次のような結果でした。

①test(i) →4227
②test(i as Integer) →5216
③test(i, j) →3453

①と③は全く同じ結果ですね。
となるとスタック領域は、メモリ環境依存ではなく
やはり仕様で決まっているのでしょうか。
①より②の方が多いのは何となく理解できます。
少なくとも単純に深さでないことは分かりました。
また暇を見つけて探ってみます。

>>540
私も、VBAを使うまでもないことにVBAを使って、
「それピボットテーブルでできるよ」
「それオートフィルタの条件指定で(ry
「ソルバー(ry
みたいな指摘を受けてしばしば鬱になります。


545:デフォルトの名無しさん
08/07/22 00:57:40
Application.MemoryTotal / MemoryUsed / MemoryFree 等で
Excelのメモリ容量を取得できるから
スタック領域もExcelの使用可能メモリ量に依存するんじゃないの?


546:y
08/07/22 01:33:32
>>545
そのプロパティ、初めて知りました。さっそく実験。
>>519の試験コードにおいて、プロパティの値を出力してみます。

Function test(i)
Debug.Print Application.MemoryUsed
Debug.Print Application.MemoryFree
test (i + 1)
End Function

予想では、再帰呼び出しがされればされるほど
使用メモリは増え、使用可能メモリは減ると思いましたが、
実際には出力される数値はまったく変化しませんでした。

スタック領域は、これらのプロパティで出力されるメモリ数とは別なのか、
それともこのプロパティは動的な意味でのメモリ容量ではないのか。



547:デフォルトの名無しさん
08/07/22 01:37:49
メモリは確保済みなんじゃないの?いや、知らないけど

548:デフォルトの名無しさん
08/07/22 02:08:06
これに書いてる
URLリンク(k-flow.blog.so-net.ne.jp)
>ちなみに、Application.MemoryFreeプロパティで得られるフリーメモリー容量は、どのような条件下においても、常に1MB程度です。
>また、Application.MemoryTotalプロパティで得られるトータルメモリ容量は、常に上記の2つのメモリ容量の合計となります。

これなら、スタックで使えるメモリ量も常に1MB程度って事じゃないかな?

549:デフォルトの名無しさん
08/07/22 02:41:04
まあ再帰の数で困ったら
まず末尾再帰の形に書き直して(ステートを持ちまわるようにする)、
それからループに書き直すといいね。

550:デフォルトの名無しさん
08/07/22 06:38:45
>>544
②だけど、>>519でやったのははtest(i as Integer)じゃなくて
test(i as Integer) as Integerだよ

ちなみにtest(i as Integer)をやってみたら5217
1違うな…

551:y
08/07/22 22:40:40
>>550
あ、すみません。②をその通りやり直したら6453でした。
>>519と比べて1だけ違いますが、これでほぼ同じ結果になりましたね。

>>549
末尾再帰と呼ばれるスキームも、初めて聴きました。Wikipedia「末尾再帰」のコード例は、全然知らない言語なので
私には理解不能です。でも、スタックオーバーフローを「回避できる」と確かに書いてあるので、できたら知っておきたいです。

色々検索したら、べき乗を求める再帰関数を末尾再帰の形に書き換えたというC言語のコード例を見つけたので
真似をしてVBAに書き直してみたのですが...
URLリンク(itpro.nikkeibp.co.jp)
(このページの一番最後に紹介されています)

Function power_loop(m As Long, n As Long, a As Long) As Long
 If n <= 0 Then
  power_loop = a
 Else
  power_loop = power_loop(m, n - 1, a * m)
 End If
End Function

Function power(x As Long, n As Long) As Long
 power = power_loop(m, n, 1)
End Function

VBAではたぶんこういうコードになるはずですが、これって、やっていることはただの再帰ですよね?
>>549の説明どおりにはできていない気がします。
演算を*でなく+にしてLong値のオーバーフローを回避した上で6000回ぐらい再帰呼び出ししたら(引数n=6000)、
案の定スタックオーバーフローになってしまいました。
ちなみにVBで書かれた末尾再帰のコード例は検索してもなかなか見つかりません。

すみません、だんだんExcelVBA固有の質問ではなくなってきたので、他スレで同じ質問をするかもしれません。

552:デフォルトの名無しさん
08/07/22 23:29:56
>>551
てか、別に末尾再帰を経なくても全然いい。普通に再帰をループになおせさえすれば。
末尾再帰という形式になった再帰呼び出しのコードは、
ループの形に必ず書き直せるという性質が成り立つだけ。
一応、どういうものかだけ↓に書いておいた。
<<末尾再帰にする前>>
function factorial&(byval i%)
if i = 0 then
factorial = 1
else
factorial = i * factorial(i - 1) ' factorial(i - 1)の前に i * という『残りの操作』が残っているので末尾再帰ではない
end if
end function
<<末尾再帰にした後 (別にVBAでは末尾再帰にしても速くなるわけでも最適化されるわけでもない。Lispなら勝手に最適化される)>>
function factorial&(byval i%, optional result& = 1)
if i = 0 then
factorial = result
else
factorial = factorial(i - 1, i * result) ' 『残りの操作』が残っていないのでこれは末尾再帰
end if
end function
<<上記をループに書き直した後(VBAでもこういう形にすればスタックなぞ一定量しか要らん)>>
function factorial&(byval r%)
dim result&
dim i%
factorial = 1
for i = 1 to r
factorial = factorial * i
next i
end function

まあなんだ、末尾再帰とか勉強したかったらSchemeとかHaskellとか勉強すればいいんじゃね?

553:デフォルトの名無しさん
08/07/22 23:32:13
ごめん。最後の関数のresult&はいらん。

554:デフォルトの名無しさん
08/07/22 23:42:09
選択範囲をset して
For Eachでまわそうとすると
余分にまわりませんか?
Selection.Countでみるとときどきなんか多い…わらし?

555:デフォルトの名無しさん
08/07/22 23:43:36
コード晒せよ

556:デフォルトの名無しさん
08/07/23 04:35:09
>>552
君、うざいよ。

557:y
08/07/23 17:10:26
>>552
なるほど、納得です。>>549の説明も意味が分かりました。
・再帰のコードは、普通のループ構造で表現できる。
・再帰のコードをいったん末尾再帰の形に直しておけば、ループ構造に直すのが容易。
・末尾再帰のコードは、『残りの操作』(戻り値を使った演算)が必要ないため、理屈としては呼出元の変数の状態を保存しておく必要がない。
・言語によっては(あるいは賢いコンパイラは)この性質を利用して、末尾再帰のコードを、同一関数のくり返しの形(ループ構造)に最適化してくれる。
 だから呼び出しのたびにスタックリソースの消費が増加することがない。
・でもVBAではそういう最適化はしてくれないから、最初から自分でループ構造に直して書く。

ありがとうございました。

>>554 >>555

558:デフォルトの名無しさん
08/07/23 17:15:16
VBAで、GUID(グローバル一意識別子)を取得したいのですが、
なにか関数などはありますか?
GetGUID的な、都度ユニークなIDを返してくれるような。
C++の方法はわかるのですが、VBAでやる方法がわかりません。
よろしくお願いいたします。

559:y
08/07/23 17:39:34
>>558
手元にあるリファレンスブックをざっと見ましたが、
そういう関数は私には見つけられませんでした。

その識別子を何に使いたいのか教えてくれたら、
他の方もアドバイスしやすいと思います。

560:デフォルトの名無しさん
08/07/23 20:16:36
>>557
だいたいその認識でOK。
誤解の無い様に言っておくが、(勘違いしていたらすまんこ)
全ての再帰がループに直せるわけじゃなくて、末尾再帰だけね。

561:デフォルトの名無しさん
08/07/23 20:34:49
>>558
VB GUID 生成

562:デフォルトの名無しさん
08/07/25 11:11:35
>>559 >>561

ありがとうございます。
できました。
URLリンク(support.microsoft.com)

563:デフォルトの名無しさん
08/07/26 04:38:05
文字列の置換に関しての質問です。
以下のような記述をしているのですが、
置換してほしくないものまで置換してしまいます。

たとえば文字列A12をB12に置換したいが、
文字列A123は置換せずそのままにしたいような場合、どうすればよいのでしょうか?
ちなみにWhat:=str1とReplacement:=str2は別シートの置換リストから引っ張ってきています。

 ActiveSheet.Columns("A:A").Select
 Selection.Replace What:=str1, Replacement:=str2



564:563
08/07/26 04:44:26
>>563の追記です。
1つのセル内には複数の文字列群があるため(A12とA123が同一セルにある)
xlWhole をつけてもだめでした。

565:デフォルトの名無しさん
08/07/26 06:20:22
A123を先にB123に変換
A12を変換
B123をA123に変換
では多分駄目なんだろなぁ


566:デフォルトの名無しさん
08/07/26 06:54:00
>>563
あくまでおいらのやり方ね。状況に応じて何種類か使い分けてるね。

>>565さんのやり方。
str1の検索ワードにlenでの長さを出して、降順にソート。長い物から置換して行く。

・オートフィルタで完全一致させる物を抽出。んでマッチにしたセルを置換。

・上二つや、組み合わせで対応出来ない時はregexpのreplaceを使う。(regexpの話出ると荒れるんだよね・・・)

たぶん、検索文字列と置換文字列がデータテーブルに存在するならば、
オートフィルタか、長い順に置換で出来るような気がするよ。

567:デフォルトの名無しさん
08/07/26 06:57:31
>>564
>1つのセル内には複数の文字列群があるため(A12とA123が同一セルにある)

かぁ・・・・。
データテーブルを文字列の長い順にソートしてから、
オートフィルタの部分一致で抽出、見えてるセルにreplaceでどうかな。


568:563
08/07/26 07:57:01
>>565 >>566 >>567さん
朝早くからご回答ありがとうございます!
今日夜にでも長い順にソートで試してみたいと思います。

569:563
08/07/26 08:07:43
置換の>>563です、
あぁ・・・。
以下のような場合がマズイかもしれません。
もう少し調べたり考えたりしてみますね。

例)置換リスト A123→B123

対象データセルの文字列
A12 A123 A1234

※A1234までB1234になってしまう。

570:デフォルトの名無しさん
08/07/26 08:56:38
一旦配列に取り込んでVBAでReplaceした方がいいんじゃないのかな

571:デフォルトの名無しさん
08/07/26 09:00:50
あ、Replace関数使うんならLen関数も一緒に使うとかしないとダメだな

572:デフォルトの名無しさん
08/07/26 09:02:27
置換条件が結構厳しそうだね。
replaceだと一致は理論上の部分一致だし、
1セルに複数の文字列が入ってるとなると、オートフィルタも限界あるなぁ。

regexpのreplaceメソッドが良いような気がするけど、詳しい人の意見も聞きたいな。
セルの中で、どんな風に文字が配置されてるかが分からないけど・・・まぁ行けるかと。

A12A123A1234 のうちA123だけを置換したいなら、 "A123^A"で引っ掛けられるかな。

573:デフォルトの名無しさん
08/07/26 09:07:43
VBAのreplace使えるのって、A123もA1234も置換する場合に限られるような気がする。
もし、A123は置換するけど、A1234はそのまま、って場合にはちとまずい。


574:デフォルトの名無しさん
08/07/26 09:54:55
だから配列に取り込むんだよ

575:y
08/07/26 14:27:52
>>569
まず、>>563

>文字列A12をB12に置換したいが、
>文字列A123は置換せずそのままにしたい

と書いていますが、2つの要求同士が矛盾しているので、
そのような動作はありえません。

解決の可能性としては、>>572の「セルの中でどんな風に文字が配置されているか」がポイントです。
つまり、文字の配置に規則性があるかどうか、ということです。
たとえば>>569で、対象データセルの文字列として「A12 A123 A1234」という例が示されていますが、
これを見る限り「文字列に含まれる各単語は、スペースで区切られている」という規則性が感じられます。
もし、すべての対象データセルの文字列がこの規則に従っているなら、望みの操作は可能です。

まずはすべての文字列に共通する規則性があるかどうかを確認し、
もし上記のような規則が存在するなら、>>570>>574が薦めている
「配列にとりこむ」方法を検討してみてください。
この場合、Split関数が使えます。



576:デフォルトの名無しさん
08/07/26 15:19:23
>>569の例のように区切り文字がスペースって事なら(半角と全角が混在してるな・・・)

 ActiveSheet.Columns("A:A").Select
 For Each c In Selection
  c.Value = RTrim(Replace(Replace(c.Value," "," ") & " ", str1 & " ", str2 & " "))
 Next

とかでどうかな、遅いし全角スペースは半角になっちゃうけどね

577:デフォルトの名無しさん
08/07/26 21:04:21
何でもかんでもVBAの機能だけでやろうとすんなって。
使える物は何でも使おうぜ。
VBSだろうがAPIだろうがWHSだろうが、VBAから使える以上、VBAで良いと思うぞ。

578:デフォルトの名無しさん
08/07/26 21:27:32
Microsoft VBScript Regular Expressions
参照して、正規表現で置換かけるのはダメなん?

579:デフォルトの名無しさん
08/07/26 22:58:50
完全一致を望むならば、やはり正規表現だと思う。


580:y
08/07/26 23:48:07
>>576のレスを見て、全角と半角の混在に気づきました。
これではJoinは使えませんね...

私は正規表現は苦手で、普段はあまり使っていないのですが、
たしかにこの状況では正規表現が良さそうな気がしてきました。
半角・全角スペースどちらにもマッチしてくれる\bがかなり便利。
"\b(A12)\b" を探して "B12" にReplaceするだけで済みますね。


581:デフォルトの名無しさん
08/07/27 02:43:35
>>577
具体的にどうやるのか示せよ

582:デフォルトの名無しさん
08/07/27 08:18:41
どんな物を置換したいのか、どんな並びになってるのかが分かればマッチパターンを考える事は出来まっせ。

もし、住所録の置換なんかで、
○○県アルプス市~~ → ●●県foo市~~
××県南アルプス市~~ → △△県bar市~~
みたいなのだと、正規表現じゃないと無理ですな。

何にせよ、規則性を見つけ出してパターンを組む事から始めよう。


583:デフォルトの名無しさん
08/07/27 11:20:14
XP Excel2003で質問なのですが

480×640の画像のRGBの値を画素ごとに
R(480,640),G(480,640),B(480,640)
という配列に読み込みたいのですが可能でしょうか?


584:デフォルトの名無しさん
08/07/27 11:50:28
スレ違い

585:デフォルトの名無しさん
08/07/27 12:37:40
画素ごとに・・・ってあんた。

586:デフォルトの名無しさん
08/07/27 14:47:34
1000万画素の写真として、3000万個の配列ですか・・・。
考えただけで鬱・・・。

587:640*480がどうやったら1000万になるんだw
08/07/27 14:57:49
>>586
もし暗算が苦手でしたら、WindowsにしろLinux(Gnome)にしろ電卓アプリが付属していますので是非お使いください。

588:デフォルトの名無しさん
08/07/27 15:28:04
え・・・普通480×640って言ったら画像サイズの事じゃないの?
画素数は密度によって違うと思うんだけど。

589:デフォルトの名無しさん
08/07/27 15:46:09
>>588
画像サイズが pixel 単位表記ではない可能性の話?

仮に mm 表記で 100dpi とすると
640mm/25.4*100≒2520pixel
480mm/25.4*100≒1890pixel
2520x1890=470万画素

590:y
08/07/27 15:56:24
>>583

可能です。中級ぐらいのVBA解説書で時々見かける課題です。
まずは対象の画像ファイルをBinaryモードでOpenし、
配列変数にバイト単位で格納します。数行で済みます。
URLリンク(www.cocoaliz.com)

次に、その画像のファイル形式の仕様に沿って、画素データを抽出する
だけですが、画素ごとの色データを取得するのが目的であれば、
24bitモードのBMP形式の画像ファイルがもっとも簡単です。
他の形式の画像ファイルでも、いったん24bitのBMP形式に保存しなおして
から処理するといいでしょう。

BMP形式の仕様はこうなっています。
URLリンク(www.kk.iij4u.or.jp)

データ部には、1画素につきRGBの順で各1バイト(計3バイト)の
色データが並んでいます。(注意が必要なのは、並びが最下行から最上行の
方向になっている点です)
上記2サイトを参考にチャレンジしてみてください。

591:デフォルトの名無しさん
08/07/27 15:58:56
エクセルっていろんな事出来るんだね・・・ほんとすごいです。

592:y
08/07/27 16:24:18
すみません。>>590は「VBA解説書」→「VB解説書」の間違いです。
さすがにExcelVBAの解説書で、画像ファイル処理の例は見たことはありません。
ある意味>>584ですが、ついつい答えてしまいました。

593:583
08/07/27 16:57:26
画像サイズと画素数を混用してしまったせいで変な誤解をさせてしまったみたいです
すみませんでした。

>>590
非常にわかりやく解説していただいてありがとうございます!
ずばりこれを知りたかったんです。
ありがとうございます。

594:デフォルトの名無しさん
08/07/27 23:06:38
結局、置換の質問した人はうまく出来たのかな。

595:デフォルトの名無しさん
08/07/28 01:39:56
今頃痴漢してつかまってるよ

596:デフォルトの名無しさん
08/07/28 07:04:35
( ´_ゝ`)

597:563
08/07/28 22:36:20
ご報告が遅くなりましてすいません。置換の人です。

みなさんの知恵をお借りして、
私のつたないプログラム能力でなんとか作ってみました。

結局、セルを1つずつ読み込んで、
セル内の文字列に対してregexp正規表現 \b(str)\b で置換 
という形にしたところ、要求を満たすことができました。
みなさんありがとうございました!

598:デフォルトの名無しさん
08/07/28 22:53:14
おめでとう

599:デフォルトの名無しさん
08/07/29 11:57:03
入力された文字が漢字か平仮名かを判定することは可能でしょうか?

600:デフォルトの名無しさん
08/07/29 12:05:21
はい。

601:デフォルトの名無しさん
08/07/29 12:42:22
どうしればいいのでしょうか
教えてください

602:デフォルトの名無しさん
08/07/29 13:36:48
全てのひらがなのリストを用意し、入力された文字がその中に見つかるかどうか判定すれば宜しいのではないかと。

603:デフォルトの名無しさん
08/07/29 14:22:43
そんな無駄で面倒なことしなくても、文字コード判定すれば一目瞭然かと

604:デフォルトの名無しさん
08/07/29 16:30:33
>文字コード判定

こいつを具体的に。

605:デフォルトの名無しさん
08/07/29 20:05:58
VBAからSASを操る事は可能でしょうか。
もし可能だったら、どんな感じで行えるのかを教えてくださいませ。

606:デフォルトの名無しさん
08/07/29 20:38:51
> VBAからSASを操る事は可能でしょうか。
可能です

> もし可能だったら、どんな感じで行えるのかを教えてくださいませ。
>>1★3

607:デフォルトの名無しさん
08/07/29 22:06:22
ありがとうございました。


608:デフォルトの名無しさん
08/07/29 22:41:39
>>604
平仮名の文字コード知るには

Cells(1, 1).Value = Asc("あ") ' -32096 を返す

609:デフォルトの名無しさん
08/07/29 22:44:03
グラフを描くとき、データ範囲設定において、
A1~A12のデータがあり、A1~A6、空白データ、A7~A12と設定してグラフを描きたいのですが、
空白データの設定がわかりません。
空白データA1000~A1010を設定して、Unionで範囲結合しても駄目でした。

できる限りシートのデータ位置は移動させたくありません。
何かよい方法がありましたら教えてください。

610:デフォルトの名無しさん
08/07/29 22:48:11
>>608
で、それが>602よりも無駄でもなく面倒でもないと?

611:デフォルトの名無しさん
08/07/29 22:49:46
>>609
見せないダミーのセルに空白データを抜いてコピーするんじゃダメ?

612:デフォルトの名無しさん
08/07/29 23:00:27
>>602
もしアルファベットやらカタカナやらが入力されても漢字と判定するって事か
どういう入力があるのか知らんけど

613:デフォルトの名無しさん
08/07/29 23:11:06
>>610
-32096から-32015の値を探せば良いだけ
直接文字列の"あ"とか探すよりも効率的
意味わからないかな?

614:デフォルトの名無しさん
08/07/29 23:47:04
>>611
すでにデータが入っていて、他関数からも使うので位置は動かしたくないのです。

615:デフォルトの名無しさん
08/07/30 02:37:30
コードを手動でエクスポートするのが面倒なので、コードをすべてエクスポートしてdoxygen
するコードを書いてみました。
要はイミディエイトウインドウの内容をクリアして、Enterキーを送ってイミディエイトウインドウ
でshellコマンドを実行したいんですが、クリアする処理をすると、コマンドが送られた後
クリアされてしまいます。クリアする処理を省けば問題ないのですが、できれば出力過程も
イミディエイトウインドウに出力したいのです。気分的に。
どなたか同じような事やったことある方いませんか?

Sub prcExportVBComponents()
Set oVBComponents = Application.VBE.ActiveVBProject.VBComponents
Set oWin = Application.VBE.Windows
Set oCodePane = Application.VBE.ActiveCodePane

' prcClearImmediateWindow ' イミディエイトウインドウをクリア
' oWin.Item("イミディエイト").WindowState = vbext_ws_Normal
' oWin.Item("イミディエイト").SetFocus
' SendKeys "^a"
' SendKeys "{Del}"
'処理

Debug.Print "shell " & Chr(34) & strComponentPath & "bld.bat" & Chr(34) ' doxygenを実行
'前の行に戻ってEnter
oWin.Item("イミディエイト").SetFocus
SendKeys "{Left}"
SendKeys "{Enter}"
End Sub

616:デフォルトの名無しさん
08/07/30 07:39:21
>>615
わざわざイミディエイトウィンドウで実行しなくてもいいんじゃないの?
つまり、End Subの前の3行(コメントも入れて4行)を

Shell strComponentPath & "bld.bat"

に置き換える。

617:デフォルトの名無しさん
08/07/31 21:46:16
ブックを変更して、ファイルを閉じようとしたり、エクセルを終了
させようとすると、
「変更を保存しますか?」
とメッセージが出力されます。
ここで、「はい」、「いいえ」、「キャンセル」のどれが
選択されたかを取得する方法ってありますか?

618:デフォルトの名無しさん
08/08/01 00:26:32
あります

619:デフォルトの名無しさん
08/08/01 00:41:10
ちょっと前からこのスレ見てるけど、やけに意地悪なやつがいるな
たぶん同一人物だろう

620:デフォルトの名無しさん
08/08/01 00:45:00
いいえ

621:デフォルトの名無しさん
08/08/01 07:50:45
>>619
馬鹿?

622:デフォルトの名無しさん
08/08/01 09:16:09
わざわざ質問に答えてて充分親切だと思うよ。
方法の詳細を知りたいなら、ちゃんと質問しない方が悪い。

623:デフォルトの名無しさん
08/08/01 09:32:49
>>617
return value

624:デフォルトの名無しさん
08/08/01 15:02:50
名簿にオートフィルタを使い、名前の列(B列)で抽出された可視セルを配列に格納するプログラムを作ろうとしています。
現在、可視セルを配列に格納する部分で躓いています。
Dim i As Long
Dim hairetu() As String
Dim kasi As Long

kasi = Range("B2", Range("B2").End(xlDown)).SpecialCells(xlCellTypeVisible).Count
ReDim hairetu(kasi - 1)

For i = 0 To kasi - 1
hairetu(i) = Range("B2:B100").SpecialCells(xlCellTypeVisible).Value
Next

修正すべき箇所や効率的な方法がありましたら教えてください。

625:デフォルトの名無しさん
08/08/01 15:10:23
cells(1,1).end(xldown)
で、可視セルを1段ずつ下げて行くとか?

626:デフォルトの名無しさん
08/08/01 17:41:24
グラフで折れ線を描くとき、間にデータがないと線でつないでくれません。
ツール、オプション、グラフで線を補完すると線は引かれました。

ここで質問です。
間を補完したい項目、補完したくない項目があります。
ある項目のみ補完する方法があれば教えてください(VBAでも可)


627:デフォルトの名無しさん
08/08/01 20:48:21
データを線形補間して、別のシートに出力、グラフ生成

628:y
08/08/01 22:22:26
>>624

コードを見る限り、SpecialCells(xlCellTypeVisible)が
可視セルのコレクションを返す、ということは分かっておられると思います。
コレクションに何個のセルが含まれているかをCountプロパティで取得し、
配列の要素数を確定するところまでは、きちんとできています。

問題は、最後のForループです。今の場合は、可視セルのコレクションの
個々の要素の値を配列に格納したいわけなので、
Forループではなく、For Each ループを使うのが妥当です。
(あらかじめ、コレクションの要素を受けるための変数c as Variantを宣言しておいてください)

i=0
For Each c in Range("B2", Range("B2").End(xlDown)).SpecialCells(xlCellTypeVisible)
 hairetu(i) = c.Value
 i=i+1
Next



629:y
08/08/01 22:41:09
>>626

まずは「ツール、オプション、グラフで線を補完」の状態にしておきます。
これで基本的に補完される状態になります。

次に、補完したくない要素について、線の色を背景色と同じにし、見えなくします。
VBAで表現すると次のようになります。
ActiveChart.SeriesCollection(1).Points(4).Border.Colorindex=2
(系列1の4番目の要素の線の色を白にする)
プロットエリアの背景色が白なら、こうすることで見えなくなります。

この操作をマウスでやってみて、「マクロの記録」を
してみると分かりやすいと思います。

630:y
08/08/01 22:53:57
>>614

>>611の言いたいのは、もとのデータを移動させることではなく、
もとのデータのコピーを別の場所に貼り付けて、
そのコピーをグラフのデータとすればいいのではないか、
ということだと思います。
私も、それ以外方法が思いつきません。

別シートのA1:A6に、元シートのA1:A6を、
A8:A13に、元シートのA7:A12を、
それぞれ「リンク貼り付け」します。

そして、別シートのA1:A13をグラフのデータとします。
「リンク貼り付け」しておけば、元シートのA1:A12が変化しても
即座に反映されます。


>>615
すごい面白そうですが、私はやったことがありません。

631:デフォルトの名無しさん
08/08/01 23:50:44
コレクションのすべてに命令を掛けるループは for each が妥当だとは思うんだけど、
for でcountして回すのと、for eachでコレクションにループ掛けるのではどっちがスマートなんだろ。

今、実測出来る場所じゃないんだけど、誰か測定した事ある人いますか?


632:デフォルトの名無しさん
08/08/02 00:05:45
>>631
ほとんどかわらないみたい
URLリンク(officetanaka.net)

633:デフォルトの名無しさん
08/08/02 00:20:28
何も事情がないかぎりFor Each使ったほうが分かりやすい。

634:デフォルトの名無しさん
08/08/02 13:46:15
値渡しとか参照渡しするくらいなら
はじめからPublicで定義しといたほうがいいとおもうのはおれだけ?

635:デフォルトの名無しさん
08/08/02 14:03:54
Publicはできるだけ少なくするのが基本 なくせるならないほうがいい

636:デフォルトの名無しさん
08/08/02 14:09:22
UserForm に Application.GetOpenFilename でファイルを開くダイアログを
使ってファイルを開いた後に、UserFormにファイルをドロップできるように
なってしまったんですが、私だけですか?

637:y
08/08/02 14:16:59
>>631

基本>>633ですが、たしかに事情によっては、
コレクション対象であってもForループの方がスマートな場合もあります。
たとえば、コレクションのすべての要素を配列に格納したい場合、

i = 0
For Each tmp In myCollection
 ary(i) = tmp
 i = i + 1
Next

とすると、配列添字カウンタ変数iと、アイテム取り出し変数tmp
の2つがどうしても必要ですが、Forループなら添字カウンタ変数だけで
済みますよね。

For i = 0 To myCollection.Count - 1
 ary(i) = myCollection.Item(i + 1)
Next

カウンタ変数の加算が、For構文の中に組み込まれているのも利点で、
できるだけDo Loop ステートメントではなくFor ステートメントを使うことを
好む方も、たいていそれが理由だとか。

でも速度的には、下の例はループのたびに補正演算が入るので、ほんのちょっと
遅くなってしまうかも。


638:デフォルトの名無しさん
08/08/02 16:49:03
僕はいつもこうしてます。気分的なもので。
こっちのほうが早いような気がしてます。

lngCnt = myCollection.Count
For i = 0 To lngCnt - 1
 ary(i) = myCollection.Item(i + 1)
Next

639:デフォルトの名無しさん
08/08/02 16:51:36
VBAで大量のコレクションをループすると非常に遅くなりますよね

640:デフォルトの名無しさん
08/08/02 17:55:31
速度は気にするべきじゃない。
なんにせよ、パフォーマンスは計らないとわからないという一面もあるし。
最初はアホなコーディングさえしなければおk。

641:y
08/08/02 18:31:11
アホなコーディングといえば、初心者の頃の私は>>634をさらにつきつめたような
考えを持っていて、ある日「どの関数でもループにiを使うなら、iをパブリック変数に
しておけばいいじゃない!」とひらめいたのです。そしてその方法で2つぐらい
モジュールを書いて、「これはどんな解説書にも載っていない画期的な方法だ!」と
思い込んでいました。


642:デフォルトの名無しさん
08/08/02 18:35:13
確かに画期的だね

643:デフォルトの名無しさん
08/08/02 18:52:55
VBAはブロック単位で変数が初期化されるわけじゃないから、
初期化処理を書かないまま特定の処理部分をループにしたりすると、
前回の内容がそのまま流れてきたりしてしまうんだよなあ。

644:デフォルトの名無しさん
08/08/02 19:00:17
static i が良く分かりません。

関数1で使った変数の続きを関数2で利用する時に、
いったん、ストック用の変数に入れて、関数2の時に呼び出してる人がいたので、
staticで続ければ良いんじゃないですか?

と言ったら、無知は黙ってろ。と言われました。
staticは関数間で解放されない変数と記憶していたのですが、間違ってますでしょうか。

645:デフォルトの名無しさん
08/08/02 19:31:37
エクセルからワードに差し込むように
エクセルファイル(データ)→エクセルファイル(伝票書式)に差し込みたいけど
伝票書式側のファイルにVBAや関数組んで引っ張ったほうがいいのかな?

差込ボタンを押したら
・(データ)ファイルの一番下の行をコピー
・(伝票)ファイルの適当なところに貼り付け
・でそこをセル参照
・↑↓ボタンを押したら(データ)ファイルのデータの1行上・下をコピー、以下同

こんな感じでしょうか?
もっといい関数とやらはあるのでしょうか?
会社のPCはアクセス無いから大変だ・・

646:617
08/08/02 20:18:35
>>623

すいません。もう少し詳しく教えて頂けませんか?

647:デフォルトの名無しさん
08/08/02 20:39:25
>>645
>・↑↓ボタンを押したら(データ)ファイルのデータの1行上・下をコピー
押したタイミングで命令をするならイベントハンドラの考え方になるね。

SheetSelectionChangeイベントが良いかな。
右左をとれないようにして、keydownで設定するのも良いかも。

ここまで書いたんだけど、どんな制御にしたいかイメージが難しいです。
すいません。

648:y
08/08/02 21:16:58
>>642 >>643
その後、ループの中から別関数を呼び出し、呼び出し先関数でもループを用いる形が出てきて、
同じPublic iを使い回していたその画期的なシステムは、完全に機能不全に陥りました。

>>645
いろいろなやり方があると思います。私はむしろデータブック側に、
任意のデータを取り出すためのユーザー定義関数を実装し、
伝票書式ブック側から参照設定するやり方をよく用います。
たとえば、データの主キーが「伝票番号」である場合、
「伝票番号」を渡すとその伝票の売上日を返す関数UriageDate(dNum)、
売り先を返す関数Urisaki(dNum)、金額を返す関数Kingaku(dNum)、
などをデータブック側に定義しておきます。

そうして伝票書式ブックから参照設定でそれらの関数を
利用できるようにすれば、任意のセルにその関数を入れるだけで、
お好みのデータを取り出すことができます。
たとえば、伝票書式ブックのA1が伝票番号のセルだとすると、あとは任意のセルに
=UriageDate(A1)、=Urisaki(A1)、=Kingaku(A1)
という数式を埋め込んでおけば、A1の伝票番号を変えるだけで、
即座にこれらの関数が適切なデータを返してくれます。

伝票書式ブック側にVBAモジュールを実装し、その中で「Cells(3,4)に売り先を書き込む、Cells(4,10)に金額を書き込む」
とやっていると、伝票書式のデザインを変更したいときに柔軟に対応できませんが、
このやり方なら、数式を埋め込むセルを変えるだけで済みます。
また、参照設定さえすれば、さらに別のブックからもこれらの関数を利用できます。


649:デフォルトの名無しさん
08/08/02 21:28:15
機能不全になる前に気づけよw

650:デフォルトの名無しさん
08/08/02 21:36:20
他人に迷惑かけない限り別にいいじゃない。
641じゃないけど実際に痛い目にあうとよく覚える。

651:デフォルトの名無しさん
08/08/02 21:38:18
カスタムシート関数の場合は共有設定でも見られるのがいい

652:y
08/08/02 21:46:37
>>649
機能不全の理由が分かるまで3日ぐらいかかりましたw
初めての頃はまずそんなもんです。

>>644
間違っているかどうかは、文章だけではよくわかりません。
関数1を呼び出す関数が、関数2以外にも複数ある場合は、
それら別の関数が、関数1の中の Static i をいじる可能性があります。
本来、Static変数はそういう使い方をされるためにあるのですが、
やはり場合に応じて、いじられても良い時と、いじられたら困る時とがあります。
後者の場合は、とりあえず現在の値をどこかにストックしておく必要が生じます。


653:645
08/08/02 22:04:31
ユーザー定義関数か・・・ちょっとやってみよう

654:デフォルトの名無しさん
08/08/02 22:33:09
ちなみにユーザ定義のシート関数のパフォーマンスなら↓に載ってた。
まあ、正確だとはいえないが、VBAが決して遅くないことがわかる。
URLリンク(www.spreadsheethell.com)

655:デフォルトの名無しさん
08/08/02 23:38:08
C#圧倒的だな

656:デフォルトの名無しさん
08/08/03 00:02:13
そうね 圧倒的に遅い

657:デフォルトの名無しさん
08/08/03 00:12:51
マクロでコピー、貼り付けを記録すると
Range("A3").Select
Selection.Copy
Range("C3").Select
ActiveSheet.Paste
こうなりますが、汎用性を高めるために
  i=Activecell.row
  Cells(i,1).Select
Selection.Copy
  Cells(i,3).Select
ActiveSheet.Paste
としました。
でもコピー貼り付けが多くなったり、列入れ替えがあると列の番号の変更が大変です。
シートの上端行を名前で定義した場合、マクロで名前を使うにはどうすればいいのでしょう?
Cells(i,"顧客名").Select のように使えたらいいのですが・・・

658:デフォルトの名無しさん
08/08/03 00:15:53
Range("C3") = Range("A3") でおっけ

659:657
08/08/03 00:24:34
A3をC3にコピーするだけじゃなく
汎用性を高めるために
選択セルの行の 1列目を3列目にコピーするようにしたいのです。(実際は別ブックへ)

660:デフォルトの名無しさん
08/08/03 00:45:57
do until cells(1,j).value = "顧客名"
j = j + 1
loop

cells(i,j).copy

とか?

661:デフォルトの名無しさん
08/08/03 00:47:13
普通に[1:1].Find("顧客名").Column??

662:657
08/08/03 06:52:56
i = ActiveCell.Row
j = [1:1].Find("顧客名").Column

Cells(i, j).Select
Selection.Copy
Range("C3").Select
ActiveSheet.Paste

でうまくいきました。ありがとうございます。

663:デフォルトの名無しさん
08/08/03 22:25:28
部門テーブル
主キー 
01)部門CD  数値 4桁
02)部門カナ 文字 10桁
03)部門名  文字 20桁
04)部門略称 文字 6桁
05)作成日  日付 --桁
06)作成時間 時間 --桁
07)作成端末 数値 7桁
08)作成者ID 文字 10桁
09)更新日  日付 --桁
10)更新時間 時間 --桁
11)更新端末 数値 7桁 
12)更新者ID 文字 10桁

部門CD,部門カナ    ,部門名      部門略称 作成日 作成時間  作成端末 作成者ID 更新日   更新時間 更新端末 更新者ID  
  1,エイギョウ    営業       営業    2002/09/01 00:00:00  80001 FUJI 2002/09/01 00:00:00 80001 FUJI   


664:デフォルトの名無しさん
08/08/03 22:28:16
おっと

665:デフォルトの名無しさん
08/08/03 22:53:52
663のを教えて。


666:デフォルトの名無しさん
08/08/03 23:00:13
富士通もとうとう日本語が喋れないのが標準になったか

667:626
08/08/04 03:41:16
>>629
>次に、補完したくない要素について、線の色を背景色と同じにし、見えなくします。
一部線が引かれているところがあり、そこは見えてもらわないと困るのです。

668:デフォルトの名無しさん
08/08/04 04:00:15
>>667
データを線形補間して、別のシートに出力、グラフ生成

669:デフォルトの名無しさん
08/08/04 07:55:36
Excelの機能には限界があるんだから、Excelでできない事は自分でやらないと

670:デフォルトの名無しさん
08/08/04 08:07:21
>>667
線全部じゃなくて、要らないところだけ背景と同色にすればいいだろ。

671:y
08/08/04 14:08:37
>>667

>>670でフォローしてくださっている通り、
線全部ではなく、一部分だけを背景と同色にできます。
>>629のコード例はそのつもりで書いたもので、
系列1の線の、4つ目の線分だけを見えなくします。
つまり、点1から点4までと、点5から最後の点までは
きちんとつながっている状態です。

手作業で(マウスで)試す場合は、ある線をクリックして、
さらにもう一度クリックしてみてください。
クリックされた線分だけがアクティブになるはずです。
その部分だけに、お好みの書式を適用できます。
その動作をマクロ記録すれば、VBAでどう表現するのか
分かりやすいと思います。

>>668でもいいと思います。


672:デフォルトの名無しさん
08/08/04 14:14:19
マクロ記録はAlt, T, M, Rと覚えてしまったら楽。

673:デフォルトの名無しさん
08/08/04 15:39:51
一つの変数を複数のユーザーフォームで使いまわす方法ありますかね?

674:デフォルトの名無しさん
08/08/04 16:15:19
>>672
やめてくれ。マクロ記録するたびにあのボーカルの顔が浮かんじまうw

>>673
「使いまわす」を詳しく。

675:デフォルトの名無しさん
08/08/04 21:21:01
久しぶりにマクロ組んで保存して使おうと思ったら・・・・
マクロ有効形式でなければ保存受け付けないだの
セキュリティレベルの警告も出ないまま無効だの
ファイルが安全な場所になきゃ有効にしてくれないだの


すげーむかついた
vista視ね

676:デフォルトの名無しさん
08/08/04 22:03:41
visuta厨涙目w

677:デフォルトの名無しさん
08/08/04 22:12:52
それWindows VistaだからじゃなくてOffice 2007だからだろ。

678:デフォルトの名無しさん
08/08/04 23:57:08
2007のリボンは本当にひどい。
慣れとか言う以前に、慣れても面倒。
クリック回数が増えただけですわ。

Alt+F8 , Alt+F11 で慣れてないとVBE環境もつらい・・。

679:デフォルトの名無しさん
08/08/05 00:27:38
他に選択肢ないのがつらいね
あぁ待てばいいだけか

680:デフォルトの名無しさん
08/08/05 09:51:05
質問です。現在、ユーザーフォームを.PrintFormを使い印刷しています。
このユーザーフォームは、
上側にボタンが横一列で並んでいて
中央にコメントボックス、
下側にラベル
という形になっています。

このユーザーフォームを、コメントボックスとラベルのみを印刷、
又は印刷時にボタンを非表示にする、ということは可能でしょうか?
もしできるのであればその方法を教えてください。お願いします。

681:デフォルトの名無しさん
08/08/05 10:23:10
>ボタンを非表示にする、

という事であれば、

userform1.button1.visible = false にすれば
非表示には出来る

682:デフォルトの名無しさん
08/08/05 11:29:34
セルに文字列があり、変数に取り込みメッセージの一部に使いたいのです。

しかしセルに改行が入っていると当然メッセージでも改行されます。
改行を取り除く方法があれば教えてください。

683:デフォルトの名無しさん
08/08/05 11:38:02
vbcrlfを探して取り除く。

684:デフォルトの名無しさん
08/08/05 17:13:22
Alt+Enterでのセル内改行はvbLfのみだぞ
.Value = "a" & vbCrLf & "b"
みたいにすれば、vbCrLf での改行も不可能では無いが
普通はvbCrLfを取り除いても意味無い

685:デフォルトの名無しさん
08/08/05 20:01:44
excelでデータベースのロジカルチェックを掛ける事を考えておりまして、
つきまして、プログラム構造、モジュール構造についてアドバイスを頂きたく投稿します。

ロジカルチェック自体は、200-300個あります。
今考えているのは、1つのモジュールに、private sub で200個のプログラムを書いておき、
1つの sub で200個のチェックプログラムを call しようと考えています。

そこで質問なのですが、1つのモジュールにたくさん詰める事は好ましくないのでしょうか。
保守を考えると、private sub A010010 のように、チェック番号をプログラム名にしておけば、
Ctrl+Fの検索で、見つけやすいかなぁ。と思っています。

皆様だったらば、どのように構築していくか等、アドバイスを頂ければ幸いです。
よろしくお願いします。

686:デフォルトの名無しさん
08/08/05 20:19:44
ストアド書いて、befor triggerにしろ

687:デフォルトの名無しさん
08/08/05 21:09:25
勉強不足で申し訳ありません。ストアドプロシージャは初めて聞きました。

データベースはSASで作成されているのですが、SASを使える人が少ない上、
教育に金が掛かる&SASライセンスが高い。と言う理由で、
なるべくコストの掛からない方向を考えている次第です。
統計解析を行うので、データベースをSASから変える事は難しいです。

イメージとしては、SASで作成されたデータセットを1つのブックに統合し、
その統合ファイル上でロジカルチェックを掛けられればと思っています。

当方、ACCESSやSQLの知識が無い為に、ストアドと言う単語も初めて聞いたのですが、
やはりEXCELのみで完結させるのは難しいでしょうか。

もし可能であれば、もう少し詳しく教えていただけますでしょうか。よろしくお願いします。
情報小出しのようになってしまい申し訳ありません。

688:デフォルトの名無しさん
08/08/05 21:28:12
>>687
長い目で見れば、弊社のような専門家にお任せいただくのが一番かと存じます。

689:デフォルトの名無しさん
08/08/05 21:30:04
難しい言い回しにしなくてもいいと思うよ
URLリンク(www005.upp.so-net.ne.jp)

690:y
08/08/05 21:38:27
>>685

最適な構造は、最終的にどういう運用をしたいのか
なるべく具体的にイメージすることで見えてきます。
細部の仕様も、その過程で決まっていきます。

・常に全種類のチェックが必要か
 →状況により、「前半のチェックは省略したい」などの要求が起こりえる場合
   →Call文のコメントアウトで対応?
   →スイッチUI実装?
     →チェックする項目のプリセットを保存できれば便利?

・エラーレポートはどうしたい?
 →Excelシートに出力
 →テキストファイルに出力

・修復ロジックも実装したい?

そのプロジェクトは一人で担当しているのですか?
もし何人かでやっているのであれば、上のような点を
協働者とも相談してみてください。


691:デフォルトの名無しさん
08/08/05 21:44:58
>>689
ありがとうございます。ただ、SASでステップは走らせません:(

すいません。私の質問の仕方が悪かったようです。

データベース、解析は一切関係無いとして、
1つのEXCELブック内にあるデータ同士の整合性をチェックするプログラムが200個あります。
この200個はどのように書いて行く、もしくは作成していくべきでしょうか。
個々に呼び出す必要はなく、必ず200個全てを走らせます。
1つの標準モジュールに200個羅列して行くべきか、モジュールを分割するべきか、
はたまたストアドを利用するか・・・。

ストアドプロシージャを調べてもEXCELと関連のあるページは見つけられませんでした。

本当に申し訳ありません・・・。

692:デフォルトの名無しさん
08/08/05 21:54:01
>>690
レスありがとうございます。
組み込んだロジカルチェックは必ず全部実行させます。

エラーレポートに関しては、後々処理が出来るように、別ファイルにダンプし、ログとして集積させます。
そして、レポートを発行する際に、管理番号でオートフィルタを掛け、
マクロでレポートの形にして、発行出来るようにする事を考えています。

プロジェクトとしては、これから提案して変えて行こうと思っている段階です。
その為には、具体的にロジカルチェックをEXCELのみで掛ける事が重要と思いまして、
質問をさせていただきました。


693:デフォルトの名無しさん
08/08/05 21:56:31
>>692
運用がわからんからなんとも言えんが、パフォーマンスなんかは問題にならんの?
# そして全く無視される>688w

694:デフォルトの名無しさん
08/08/05 22:03:04
>>693
private sub で200個を1つのモジュールに記載して、
呼び出し用の sub で200個を call する事は問題が無いのか、そこが気になっています。

そこまで多くのプログラムを1つのモジュールに書いた事がありません。
本当に動くのかも悩みの種です。

統合ファイルの内訳としては、その度に変わるので一概には言えないのですが、
平均すると25-30シートで、1つのシートに多くとも2000行程度なので、問題はなさそうです。



695:デフォルトの名無しさん
08/08/05 22:37:38
>>694
・Subではなくて、FunctionでBooleanを返したほうが良いのでは?
・一つのモジュールに入る大きさのコードなら、どれだけ書こうと全く問題がない(限界を超えたら
 実行時エラーとして教えてくれる)
・保守を考えるなら、第三者が見てわかりやすい関数名にしたほうが良い
・関数名には日本語が使えて、さらに日本語を使っても全く問題がないので、日本語を使った
 関数名にするというのも一つの手

696:デフォルトの名無しさん
08/08/05 22:51:41
>>695
レスありがとうございます。
functionのboolean戻りは良いですね。
booleanで返した時に、エラー項目を引っ張る際にもう1段踏まないと行けないのがつらそうですが、
何とか対処出来そうです。

やはりモジュールに限界はあるのですか・・・。でも実行時エラーが出るなら安心ですね。

実はチェックリストが存在していて、そのチェックリストを基にプログラムを組むので、
チェックNo.のコードを関数名にするのが良いと思いました。

アドバイスありがとうございます。


697:デフォルトの名無しさん
08/08/05 23:02:38
200ねえ…
そんな量じゃなければ、私ならインタフェース使ってクラス量産かな。
(なんせ200もクラスがあるとウザいので)
これなら処理を値として扱える。

698:デフォルトの名無しさん
08/08/05 23:05:49
>>697
ですよねぇ・・・。
一つ一つは小さい処理で、日時の整合性を確かめたりする程度なのですが、
何せ200-300、プロジェクトによってはもっと増える事もあるんですよね。
だから、作成者と保守者が別でもわかりやすいように、と色々考えてはいるのですが、
なかなか纏まらない感じです。

皆様、アドバイスありがとうございました。
2-3日、無い知恵絞って頑張ってみようと思います。

本当にありがとうございました。失礼します。

699:y
08/08/05 23:09:40
>>694

>private sub で200個を1つのモジュールに記載して、
>呼び出し用の sub で200個を call する事は問題が無いのか
私も、これ自体は問題ないように思います。
少し上のほうのレスに、再帰呼び出しの話題がありますが、
数百個ぐらいなら、たとえネスト呼び出ししても大丈夫です。
コードの長さについては、万が一どうしても収まらない事態になれば
別々の標準モジュールに分割してもいいでしょう。
その場合、各ロジックチェックはPublicスコープにする必要がありますが、それが
嫌であれば、クラスモジュールに書いてFriendスコープにしておく手もあります。
いずれにしても、取り返しのつかない結果になる心配はありません。
常に200のチェックを行い、カスタマイズの可能性も無いのであれば、
まず1つのモジュールに羅列しておくのがシンプルで良いかと。

>>695の >・Subではなくて、FunctionでBooleanを返したほうが良いのでは?
と同じことを考えていましたが、エラーログ出力部となるプロシージャをどのように
配置するかによって、2通りの構造が考えられます。
ロジカルチェックをFunctionで書いて、呼び出し元にエラーチェック結果を返し、
呼び出し元からエラーログ出力プロシージャを呼ぶのか、
あるいは、ロジカルチェックをSubで書いて、エラーが検出されたらそのSubから
エラーログ出力プロシージャを呼ぶのか。
単純に「エラーがあった、なかった」だけのレポートで済むのであれば、
Bool値を返すFunctionでいいと思いますが、「どのようなエラーなのか」まで
表現したい場合は、後者の方が都合がいいかもしれません。


700:デフォルトの名無しさん
08/08/05 23:12:36
COM経由で呼べる組み込み言語ってないだろうか。
適当にJScriptインタプリタ起動できたりしないのだろうか。厳しいかな。

701:デフォルトの名無しさん
08/08/05 23:31:26
ときどき 0& ってのを見るんだけど、これってどういう意味ですか?
If Len(buf) = 0& Then~ みたいな感じです

702:デフォルトの名無しさん
08/08/05 23:37:33
Long型の0

703:デフォルトの名無しさん
08/08/05 23:38:51
ごめん うそ

704:デフォルトの名無しさん
08/08/05 23:45:50
>>700
Microsoft Script Control

705:デフォルトの名無しさん
08/08/06 00:27:14
>>704
thx!

706:デフォルトの名無しさん
08/08/06 11:07:42
範囲(行のみ下がる、列数data_nは同じ)が離れているセルの値を、その範囲だけ、二次元配列に格納したいです。

仮に範囲数が4つなら二次元配列は(4,data_n)

unionで範囲を結合しても3つまでしか結合できませんでした。

だから1つずつ範囲から値を配列に格納しようとしていますがうまくいきません。

どのように配列定義、範囲から二次元配列への格納をすればよいでしょうか?


707:y
08/08/06 18:02:38
>>706

>範囲数が4つなら、二次元配列(4, data_n)
という点から想像すると、それぞれの範囲は1行×data_n列のサイズになっている
ということですか?

まず配列の定義ですが、特に設定を変えない限り、配列の番号は0から始まるので、
(4, data_n) と定義すると、実際には 5 × (data_n + 1) 個分の配列が
準備されます。本当にそれでいいかどうか確認してください。

次に格納の仕方ですが、
>1つずつ範囲から値を配列に格納しようとしていますがうまくいきません。
この考え方でも大丈夫です。中途半端でも構わないので、
とりあえず書いたコードを貼ってみてください。


708:デフォルトの名無しさん
08/08/06 19:37:01
春日部市1-2-3のような文字列の数字部分のみ半角に変換する方法を探していたら
次のようなマクロを見つけました。

Sub MacroR()
Dim idx As Integer, trg As Range
 Set trg = ActiveSheet.Cells.SpecialCells(xlCellTypeConstants, xlTextValues)
 For idx = 0 To 9
  trg.Replace What:=Right(StrConv(Str(idx), vbWide), 1), Replacement:=Right(Str(idx), 1)
 Next
End Sub

ここでRight関数を使っているのは、Str関数だと先頭に符号が付くからですか?

これのReplaceの部分を
  trg.Replace What:=StrConv(CStr(idx), vbWide), Replacement:=idx
に変更すると同じ事が出来たのですが、これだと何か不都合が出たりしますか?

709:デフォルトの名無しさん
08/08/06 19:44:55
変数のスコープについて教えてください。
全ての標準モジュールで使用出来る範囲を付与するには、
どの部分に、どのように宣言したらよろしいのでしょうか。

710:y
08/08/06 20:06:42
>>708
あなたのコードの方が良いように思います。
ReplacementのところはCstr(idx)にするとより丁寧です。


711:y
08/08/06 20:11:16
>>709
付属のヘルプで、
「Public ステートメント」
「Public ステートメントの使用例」
を検索してみてください。


712:デフォルトの名無しさん
08/08/07 00:01:04
>>709
つりですか?

713:デフォルトの名無しさん
08/08/07 09:47:54
>>707
はい1×data_nです。

Dim data AS Variant

search=0
if 該当の行が見つかったら then
search=search+1


data(search) = range(cells(search,data_n),cells(search,data_n))

endif

複数行をまとめて配列に移したいのです。
unionでダメでした。
妥協するならせめて一行をまとめて移したい。
上記は妥協コードです。


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch