プロが教えるわが家の防犯対策術!

請求書(sheet21)に税率(10又は8)を表示したく、添付したコードを作成したのですが作動しません。また、ディバックも表示されず、原因がわかりません。作成したコードは、Sheet21のB16~B23セルに商品コード100~1000及びSK01~SK200から商品名に応じた8個の商品コードを入力し、N16~N23セルに、100~1000までは「10」を SK01~SK200までは「8」を表示すると思ったのですが、素人では無理でした。
Sub 消費税率判定()
Dim n As Long
Dim Sh21 As Worksheet
Dim i As Integer
Set Sh21 = Worksheets("b16:N23")
n = WorkSheetFanction("sh21").CountIf(Range("B16:N23"), "<>")
For i = 100 To 1000
Next

If Sh21.Range("B16:B23").Value = i Then
Range("N16:N23").Value = 10
Else
Range("N16:N23").Value = 8

MegBox ("税率は正しいですか")

End If

End Sub

質問者からの補足コメント

  • 画面を添付します。

    「VBA 税率を判定表する方法を教えて下さ」の補足画像1
      補足日時:2022/03/28 12:29
  • こんばんは。頂いたコードを試行しました。
    B16:B23セルに商品コードを入れてみましたが、N16:N23セルに税率が表示されず0表示なので、マクロを実行すると,メッセージ×13 「消費税算出はできませんでした。型が一致しません」と表示されたので「OK]ボタンで押すと、該当のNセルに税率が表示されました。解決方法を教えて下さい。

    No.6の回答に寄せられた補足コメントです。 補足日時:2022/03/28 20:14

A 回答 (10件)

消費税を算出する処理にセル情報は無関係なので別関数にしましょう。


また、100未満、1000超、1未満、200超、数値でない可能性を考慮し、エラーハンドリングをしましょう。


Option Explicit

'
' 消費税エリアを処理します。
'
Public Sub 消費税率判定()
On Error GoTo Exception

Dim sheet As Worksheet
Dim itemCodeRanges As Range
Dim itemCodeRange As Range

Set sheet = Worksheets("請求書")
Set itemCodeRanges = sheet.Range("B16:B23")

' 消費税列をクリア
itemCodeRanges.Offset(, 12).Value = vbEmpty

' 消費税を設定
For Each itemCodeRange In itemCodeRanges
itemCodeRange.Offset(, 12).Value = getTax(itemCodeRange.Value)
Next
Call MsgBox("税率は正しいですか")
Exit Sub

Exception:
Call MsgBox(Err.Number & vbCrLf & Err.Description, vbOKOnly + vbCritical, "エラー")
End Sub

'
' 消費税を求める。
' @param itemCode 商品コード。
' @return 消費税。
'
Private Function getTax(itemCode As String) As Long
On Error GoTo Exception

Const ReducedTaxRateItemPrefix As String = "sk"

' 消費税範囲グループ
Dim taxGroups(1) As Variant
taxGroups(0) = Array(100, 1000, 10)
taxGroups(1) = Array(1, 200, 8)

Dim targetItemCode As String
targetItemCode = LCase(itemCode)

' 消費税範囲を特定
Dim tax() As Variant
If InStr(targetItemCode, ReducedTaxRateItemPrefix) = 0 Then
tax = taxGroups(0)
Else
tax = taxGroups(1)
End If

' 消費税の決定
Dim itemCodeNumber As Long
itemCodeNumber = CLng(Replace(targetItemCode, ReducedTaxRateItemPrefix, ""))
If tax(0) <= itemCodeNumber And itemCodeNumber <= tax(1) Then
getTax = tax(2)
Exit Function
End If

Call Err.Raise(1000)
Exit Function

Exception:
Call Err.Raise(Err.Number, Err.Source, "消費税算出できませんでした。" & vbCrLf & Err.Description, Err.HelpFile, Err.HelpContext)
End Function
この回答への補足あり
    • good
    • 0
この回答へのお礼

有難うございます。試行してみます。

お礼日時:2022/03/28 17:22

なるほど、失礼しました。


Qchan1962様のおっしゃる通りですね。
では、getTax()に渡す商品コードを得ることができないなら、処理を終わらすなどすれば良さそうですね。

質問者様の全体的な処理の流れが分かりませんが、入力された行ずつに何かを処理しているなら、そこにgetTax()を混ぜ込んで処理することでも可能でしょう。
    • good
    • 1
この回答へのお礼

有難うございます。確かに一度ご入力した行の商品コードを消去した場合、
税率セルの数字はそのまま表示されたままです。No8でご返答しました、
「消費税率判定」ボタンで消去できますが、ご指導の「入力された行ずつに何かを処理しているなら、そこにgetTax()を混ぜ込んで処理する」こともやってみたいと思います。

お礼日時:2022/03/30 09:23

すみません。

少しお借りします
naktak様 請求書と言う事で必ず範囲が埋まっているとは限らないと思います。
従って、空白セルに対しての処理が必要になると思いますが・・
違っていたらごめんなさい。
    • good
    • 1
この回答へのお礼

有難うございます。ご指摘いただいたとおり、一度入力してしまったセルを消去した場合、消費税率セルだけは消去されませんでした。

お礼日時:2022/03/30 09:29

全角数字でも入ってるんじゃないですか?


そのエラーはSKを除いた値が数値に変換できないから出てますので。
    • good
    • 0
この回答へのお礼

遅くなりました。メッセージはでますが、入力画面に「消費税率判定」ボタンを作成し、入力の最後に処理するようにしました。コード入力項目すべて消費税率が一括表示されたので助かりました。これでインボイス問題に対応できそうです。有難うございました。

お礼日時:2022/03/28 21:38

ご質問の回答ではありませんが


本来は、請求書に直接入力を行って処理するのはどうなのかなと思います
出来るだけ元データ(作成するためのデータ)は、一元化するのが良いと思います。受注ー>納品ー>請求 みたいに1つ前のデータで作られる形
と考えると受注データを入力、納品データを操作して請求書を作る流れになるかと・・

なので、商品一覧表を基軸に考えた方が品番はもちろん品名や単価A・B・C税率など操作し易くなると思いました。
他にも顧客一覧(情報)などが必要ですし、(実績)蓄積データも必要かと
そう考えると基幹業務をVBAで作成するには、少しスキルが必要になるのかなと思いました。

この回答に逆行するような回答ですが、
B列入力時に出力してしまう と言う方法も考えられます。
(私的には比較的よく使います(処理速度をごまかす為)受注入力などで使えると思います)

一応、コードです。対象のシートモジュールに記載しますが
すでにWorksheet_Changeイベントを使われている場合は使われている
Worksheet_Change内に組み込む必要があります。
(サンプルなので少しやっつけ感ありますが添削してくださいね)
当然あるであろう値の削除、選択範囲に入力していくような手順にも
取り合えず対応してみました。(該当品番以外を入力するとメッセージ出力後、元の値に戻ります)

Option Explicit

Dim flag As Boolean
Const iKey As String = "sk"
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range
flag = False
If Intersect(Target, Range("B16:B23")) Is Nothing Then Exit Sub
Application.EnableEvents = False
If Target.Count > 1 Then
For Each r In Selection
Call process1(r)
Next
Else
Call process1(Target)
End If
If flag = False Then
MsgBox ("登録品番では有りません")
Application.Undo
End If
Application.EnableEvents = True
End Sub

Sub process1(Target As Range)
With Target
If .Value = "" Then .Offset(, 12).Value = "": flag = True: Exit Sub
If InStr(.Value, iKey) = 0 Then
If .Value >= 100 And .Value <= 1000 Then .Offset(, 12).Value = 10: flag = True
Else
If CInt(Split(.Value, iKey)(1)) >= 1 And CInt(Split(.Value, iKey)(1)) <= 200 Then
.Offset(, 12).Value = 8
flag = True
End If
End If
End With
End Sub

ここ迄書いて思いました。ひょっとしてB列の値は入力では無いですね
多分。それはそうですよね。。。入力でなければ、意味ないですね。。
まぁ、せっかく?書いたので掲示します。
    • good
    • 0
この回答へのお礼

有難うございます。試行します。B列はその都度入力しています。

お礼日時:2022/03/28 20:16

添付図を掲示される前に作成したコードなので


条件が質問文にある SK 大文字 となっています
図のように skとするといかがでしょうか
修正箇所 If InStr(r, "SK") = 0 Then など 3か所
このキーが変わらない場合は以上で良いと思いますが、

全角半角、大文字小文字が混在するような場合、
右辺と左辺を同じにして比較する必要がありますので
大文字か小文字にUCase関数 LCase関数などで合わせます
また、全角半角なども処理上、合わせる場合、StrConv関数を使用します
上記関数については
UCase関数 LCase関数 StrConv関数、などで調べてみてください。
    • good
    • 0
この回答へのお礼

有難うございました。すみません。大小文字を考えず投稿してしました。小文字に統一致します。

お礼日時:2022/03/28 14:27

連投すみません


>その都度請求する品目数が8品目以内と少ないので、商品コードはコード一覧表から手入力しています。

そっちでなく、条件を一覧表から取得した方が良くないかなぁ と思いました
また、一覧表があるなら、そこに税率項目を設定して
Vlookupなどの関数でも良さそうですが、VBAは他の処理も同時に出来るので、そのあたりの処理方法は何かを推奨する訳ではありません
    • good
    • 0
この回答へのお礼

いつも有難うございます。今日の段階では、入力シート内で出来る方法をと思っています。消費税率を手入力していますので、自動入力で消費税率の誤入力を防ごうと思っています。ご指導の商品一覧表に税率項目を設定してのVlookup関数の方も別途作成してみます。
なお、#2を修正し実行してみましたが作動しませんでしたので、ディパックにて確認したら最後から、If InStr(r, "SK") = 0 Then のところに帰ります。すみません。教えて下さい。よろしくお願いします。

お礼日時:2022/03/28 13:39

#2です


訂正です  If r >= 1 And ではなく If r >= 100 And ですね
    • good
    • 0
この回答へのお礼

有難うございました。実行しましたが、税率のN16~N23セルに数値が表示されませんでした。ご指導お願いします。

お礼日時:2022/03/28 13:42

こんにちは


コードとご説明から推測すると

Sub 消費税率判定()
Dim Sh21 As Worksheet
Dim Rng As Range
Dim r As Range

Set Sh21 = Worksheets("請求書")
Set Rng = Sh21.Range("B16:B23")

For Each r In Rng
If InStr(r, "SK") = 0 Then
If r >= 1 And r <= 1000 Then r.Offset(, 12).Value = 10
Else
If CInt(Split(r, "SK")(1)) >= 1 And CInt(Split(r, "SK")(1)) <= 200 Then
r.Offset(, 12).Value = 8
End If
End If
Next
MsgBox ("税率は正しいですか")
End Sub

ちょっと分かりにくい書き方で申し訳ないのですが、こんな感じかな?

商品コードはVBA内で設定していますが、実際にはシートに書いてあるのではないかと・・
    • good
    • 0
この回答へのお礼

有難うございます。その都度請求する品目数が8品目以内と少ないので、商品コードはコード一覧表から手入力しています。

お礼日時:2022/03/28 12:44

コードは無視します。


シートのどこに何があるかを、正確に記述してください。
図を添付していただけると尚いいです。
    • good
    • 0
この回答へのお礼

有難うございます。画面を添付しました。

お礼日時:2022/03/28 12:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!