EXCELのマクロで数値比較の不整合をチェックする方法

このQ&Aのポイント
  • EXCELのマクロを使用して「数量」「単価」「金額」の表の不整合をチェックする方法をまとめました。
  • マクロを使って、「金額」欄と「数量」「単価」の計算結果が一致しない場合、マクロは「計算違い」と表示します。
  • しかし、一部の場合において「計算違い」と表示されることがあり、問題の特定ができていません。
回答を見る
  • ベストアンサー

EXCELのマクロで数値比較

「数量」「単価」「金額」のEXCELの表があり「金額」欄が「入力」であったり「計算式」であったりするため「金額」の不整合をチェックするマクロを作りました。(コードの一部は下記) For cntR = 5 To MaxRow If Cells(cntR, 8).Value <> _ Application.RoundDown(Cells(cntR, 6).Value * Cells(cntR, 7).Value, 0) Then Cells(cntR, 23) = "計算違い" End If Next 計算違いとは思えないのに”計算違い”となってしまいます。 テストした表の内容 数量:200 単価:20、20.1、20.3・・・・・20.9、21 金額:=数量*単価の計算式が入っている。 マクロ実行後”計算違い”となってしまうケース。 単価:20.1と20.4の時 ※金額に手入力してみる:”計算違い”になりません。 ※金額欄の計算式を変えてみる=Rounddown(数量*単価,0):”計算違い”になりません。 どこに問題があるのか特定できずにいます。 EXCEL2007・2000の両バージョン下でマクロに手を加えてます。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。 どうも最近、あまり脱線して書くことはできないようですが、ワークシートには、独特の誤差修正が施されていますが、完全には駆逐できていません。せめて、0.1%以下程度にしてくれればとは思いますが、これは、Microsoft 側の開発側の問題で、IEEE 754 の Double 型をそのまま使用していることが原因です。決して、Microsoft 側の言う、IEEE 754(電子規格)だけの問題ではないと思うのです。 http://support.microsoft.com/kb/78113/ja Excel で浮動小数点演算の結果が正しくない場合がある しかし、その反面、VBA側は、Double型の約半分ぐらいが、そのままの丸め誤差が発生します。それを、どう処理するかであって、一般のユーザーは、その原因を細かく追究しても始まりません。 Cells(cntR, 6).Value Cells(cntR, 7).Value どちらかは分かりませんが、小数点のあるほうは、そのまま、ダイレクトで代入できません。 曲がりなりにもワークシート側で処理されたものと、VBAでの小数点の演算を、そのまま比較するということは出来ません。ワークシートでは、小数点の掛け算自体には、それほどに誤差が発生していないはずです。 VBA(VB6のマニュアルに出てくる)では、浮動小数点誤差対策としては、小数点固定法というものと、整数変換法という方法があります。 今回は、10倍という方法で比較するなら、これは、整数変換法ということにはなるとは思いますが、それを、10で割ってやっても誤差は出ないはずです。 = 単価 * 数量  ↑ VBAでは、ここがDouble型になります。 If (Cells(cntR, 8).Value <> _ (Cells(cntR, 6).Value * Cells(cntR, 7).Value, 0 * 10)/10 Then 通常は、このように、Currency型に変換する方法が使います。 ただし、ワークシート側には、今回は、小数点の誤差は出ていないことを前提としています。(ワークシートには、引き算、割り算でも必ず誤差が出ます) '------------------------------------------- ' Dim cntR As Long Dim MaxRow As Long MaxRow = Range("H65536").End(xlUp).Row   For cntR = 5 To MaxRow   If Cells(cntR, 8).Value <> _     CCur(Cells(cntR, 6).Value * Cells(cntR, 7).Value) Then      Cells(cntR, 23).Value = "計算違い"   End If  Next End Sub

Excel-VBA
質問者

お礼

質問は締めきりますが、貴重な勉強をさせていただき感謝します。 まだまだ初心者ではありますが、今後に必ず役立つものと思います。

その他の回答 (1)

  • FEX2053
  • ベストアンサー率37% (7987/21355)
回答No.1

こいつが原因かもですね。 http://pc.nikkeibp.co.jp/pc21/special/gosa/eg1.shtml RoundDownするってことは、.999999を切り捨てるってことなので。 小数があるなら、一旦整数化して計算するなりしないと。

Excel-VBA
質問者

お礼

下記コードのように修正し解決できました。 ありがとうございました。 If Application.RoundUp(Cells(cntR, 8).Value * 10,0) <> _ Application.RoundDown(Cells(cntR, 6).Value * Cells(cntR, 7).Value, 0) * 10 Then Cells(cntR, 23) = "計算違い" End If

関連するQ&A

  • EXCELマクロの処理時間を短縮したい

    EXCELマクロの時間短縮で悩んでいます。どうかお知恵をお貸し下さい。(長文です) Windows XP Pro EXCEL 2002 を使用しています。 以下の作業の2.のところで2分以上 3.のところで2分以上の時間が掛かっています マクロソースによるこれ以上の短縮は望めないでしょうか?  <作業内容> 1. OLEDBを使って他のDBから  トランザクション「A」のデータを シート「A」に  マスタ「M」のデータを シート「M」に展開しています 2. シート「A」のデータは 約40,000件 (変動します)  番号    基本番号+枝番(1桁) 最初は基本番号+0で変更があると枝番をカウントアップして追加  最新番号  変更が合った場合 変更の回数(枝番=0のレコードだけ更新)  コード   名称コード   数量    単価    小数点以下 2桁まで  追加数量    追加単価   番号  |最新番号|コード| 数量 | 単価 | 追加数量|追加単価|   1000010 | 0 |123456| 1,000|100.30| 10|1,000.00|   1000020 | 2 |111111| 1,000|200.50| 1|5,000.00|   1000021 | 0 |111111| 900|200.50| 2|5,000.00|   1000022 | 0 |111111| 1,000|200.00| 1|5,000.00|   1000030 | 0 |123000| 2,500| 90.75| 0| 0.00|   9500010 | 0 |999999| 0| 0.00| 0| 0.00|  これを シート「一覧」に基本番号別に枝番が最新の行をコピーして金額を出します  約 35,000件になります  基本番号 |コード| 名称 | 数量 | 単価 | 追加数量|追加単価| 金額   100001 |123456| | 1,000|100.30| 10|1,000.00|110,300   100002 |111111| | 1,000|200.00| 1|5,000.00|205,000   100003 |123000| | 2,500| 90.75| 0| 0.00|226,875 3. シート「M」のデータは 約30,000件 (変動します)   コード |  名称  |    111111| AAAAAAAAAA | 123000| ABCDEFGHIJ | 123456| BBBBBBBBBB |  シート「一覧」の名称に名称を入れます  基本番号 |コード|  名称 | 数量 | 単価 | 追加数量|追加単価| 金額   100001 |123456|BBBBBBBBBB| 1,000|100.30| 10|1,000.00|110,300   100002 |111111|AAAAAAAAAA| 1,000|200.00| 1|5,000.00|205,000   100003 |123000|ABCDEFGHIJ| 2,500| 90.75| 0| 0.00|226,875 <マクロ ソース> Sub 一覧作成() Dim i As Long, j As Long, k As Long, read_no As Long Dim jlist As Worksheet, jdata As Worksheet Dim v As Variant, w As Variant Dim dic As Object Application.ScreenUpdating = False '画面停止 'DB取り込み ※省略 Set jlist = Worksheets("一覧") '処理2 Set jdata = Worksheets("A") jlist.Cells.ClearContents jlist.Range("A1").Value = "基本番号" jlist.Range("B1").Value = "コード" jlist.Range("C1").Value = "名称" jlist.Range("D1").Value = "数量" jlist.Range("E1").Value = "単価" jlist.Range("F1").Value = "追加数量" jlist.Range("G1").Value = "追加単価" jlist.Range("H1").Value = "金額" i = 2 '今読んでる行 k = 2 '書いている行 j = 0 '枝番が合った場合 飛ばす行 read_no = 0 Do While jdata.Cells(i, 1).Value < 9500000 read_no = jdata.Cells(i, 1).Value / 10 j = 0 If jdata.Cells(i, 2).Value <> 0 Then '枝番有 j = judata.Cells(i, 2) End If i = i + j jlist.Cells(k, 1).Value = Format(read_no, "000000") jlist.Cells(k, 2).Value = jdata.Cells(i, 3).Value jlist.Cells(k, 4).Value = jdata.Cells(i, 4).Value jlist.Cells(k, 5).Value = jdata.Cells(i, 5).Value jlist.Cells(k, 6).Value = jdata.Cells(i, 6).Value jlist.Cells(k, 7).Value = jdata.Cells(i, 7).Value jlist.Cells(k, 8).Value = _ Application.RoundDown((jdata.Cells(i, 4).Value * jdata.Cells(i, 5).Value + _ jdata.Cells(i, 6).Value * jdata.Cells(i, 7).Value), 0) k = k + 1 i = i + 1 Loop Set jname = Worksheets("M") '処理3 With jname With .Range("B2", .Cells(.Rows.Count, 1).End(xlUp)) v = .Columns(1).Value w = .Columns(2).Value End With End With Set dic = CreateObject("scripting.dictionary") For i = 1 To UBound(v) dic(v(i, 1)) = i Next With jlist With .Range("B2", .Cells(Rows.Count, 4).End(xlUp)) 'B2~Dの最終行まで v = .Value For i = 1 To UBound(v) If dic.exists(v(i, 1)) Then v(i, 2) = w(dic(v(i, 1)), 1) Else v(i, 2) = "無" End If Next With .Offset(0, 0) .ClearContents .Value = v End With End With End With Set dic = Nothing Set jlist = Nothing Set jname = Nothing Application.ScreenUpdating = True End Sub

  • エクセルマクロで数値の一致ができない

    マクロで以下のコードを作成しましたが、うまくいきません。 If Left(Cells(3, 2).Value, 5) = Cells(3, 6).Value Then ……………………… End if Cells(3, 2),Cells(3, 6)の値が数値だと見かけでは一致していますが、 一致していないとされています。 ■うまくいかない Cells(3, 2)…123456789 Cells(3, 6)…12345 Cells(3, 2),Cells(3, 6)を文字に変えると問題なく動作します。 ■うまくいく Cells(3, 2)…abcdefgh Cells(3, 6)…abcde Cells(3, 2),Cells(3, 6)を数値でもうまくいくにはどうしたらいいのでしょうか。 よろしくお願いします。

  • ExcelのマクロをAccessで動かすには…

    今までExcelを使用していてVBAも段々と理解してきたのですが 今回Accessを使用することになって詰まってしまいました。 下のようなExcelのマクロ(VBA)があるのですが、 これをAccessでも同じように動かしたいのですがわかりません(汗) ----------------------------------------------- Sub テスト() Dim GYO As Long GYO = 1 Do Until Worksheets("テスト").Cells(GYO, 1).Value = "" If Worksheets("テスト").Cells(GYO, 1).Value >= 80 Then Worksheets("テスト").Cells(GYO, 2).Value = "合格" Else Worksheets("テスト").Cells(GYO, 2).Value = "不合格" End If GYO = GYO + 1 Loop End Sub ----------------------------------------------- これでAccessのレコード一つ一つの合否を入力する欄に 自動で入力されるようにしたいのですが、 Accessでの記述方法がよくわからないのです。(^_^;) お詳しい方、よろしくお願いしますm(_ _)m

  • エクセル2000で見積書の印刷

    エクセル2000で作成した見積書があるのですが、内訳の中で、例えば 品名、 規格、単位、数量、単価、金額 の欄があり 金額の欄のセル内に=数量*単価の計算式が入っています。 項目の内、数量が1個、とか1式の場合に限り、印刷の時に単価の金額だけを空白で印刷したいのです。(今までは全て印刷していました。) もちろん金額の欄に直接入力しちゃえば良いのですが、金額欄のセル内の計算式はいじりたくないのです。VBAが今ひとつわからず悩んでいます。 わかり難かったら補足いたしますのでよろしくお願いします。

  • マクロの構文でわからない所があります

    エクセル2013です。 退職者の作成したマクロの中で 何を処理しているのか、わからないところが あります。 以下の構文ですが、 これは、何がどうした時、どういう処理 をするのでしょうか? f8を押しながら見ていてもよくわかりません。 よろしくお願いします。 Do While Cells(Z, 6).Value <> "" If Cells(Z, 1).Value <> "" Then Sheets("集計表").Cells(Z, 1).Value = Cells(Z, 1).Value Else: Sheets("集計表").Cells(Z, 1).Value = "-" If Cells(Z, 5).Value <> "" Then Sheets("集計表").Cells(Z, 5).Value = Cells(Z, 5).Value Else: Sheets("集計表").Cells(Z, 5).Value = "-" If Cells(Z, 6).Value <> "" Then Sheets("集計表").Cells(Z, 6).Value = Cells(Z, 6).Value Else: Sheets("集計表").Cells(Z, 6).Value = "-" Z = Z + 1 Loop

  • vlookup関数で求めた数値の合計

    excelで20行まで入力できる発注書を作っています。 vlookup関数で商品コードを入力すると、商品名と単価は自動で表示されています。 単価×購入数量で商品毎に購入金額を求め、総合計を自動計算させたいのですが、、、 発注書には必ず20品目入力されるわけではありません。 この入力されない商品行の合計金額は#valueとなっています。 結果として総合計も#valueとなってしまいます。 どなたか総合計を求める方法をご教示ください。 宜しくお願いいたします。

  • エクセルで数値を表示させたくない。

    いつもお世話になっています。 ROUNDDOWN(A1*B1,0) と関数を入力しました。 でも、数量を入力(A1や B1に)しないと、0と表示されてしまいます。 数量を入力しないでも 0と表示されないようにするにはどうしたらいいでしょうか?  答えの欄 (C1)は、無地にしておきたいのです。 どうかよろしくおねがいします。

  • EXCELで先入先出の商品有高帳

    こんにちは。 EXCELで先入先出についてお聞きします。 ヘッダ部に品番を配置し 日付、受入欄(数量、単価、金額)、払出欄(数量、単価、金額)、残高欄(数量、単価、金額)の項目で EXCELで先入先出の商品有高帳を作成したいのです。 移動平均でしたら払出の単価欄は1行前の残高の単価や残高欄の数量欄は受入数計-払出数計、 金額欄は受入額計-払出額計、単価欄は金額÷数量といった式を設定しましたが 先入先出の場合、式の設定といったら金額欄に数量×単価程度で、残高欄も 単価によって変わってきますので手入力と考えましたが 効率良く商品有高帳を入力する為に、どのような式を設定していますか? 最悪、ほとんどが手入力になってしまうのでしょうか? 分かる方おられましたら、教えて頂けないでしょうか。 宜しくお願いします。

  • マクロif文での条件式について

    マクロ初心者です。Excel2003を使用しています。 仕事上で使用しているエクセル表より、ある値以上の項目を抽出し、その値を用いて計算結果を出すためのマクロを作成いたしました。いろいろなサイトを参考にして自分なりに書いてみたのですが、どうしてもうまくいきません。 表は簡単なもので、以下のようなものです。 1 9 2 24 3 45 4 67 1列目は使用濃度、2列目は測定値です。この測定値が30より大になった項目を抽出し、計算式にその値を代入し計算結果として出したいのです。また、全ての測定値が30以下だった場合は、計算結果の欄に”<30”とのように表示をさせたいと考えています。 以下のようにマクロを書いてみました。 Sub Macro1() For i = 1 to 4 if Worksheets("sheet1").cells(i , 2).value <=30 then Range("A5")=0 '測定値が=<30だった場合は計算をしないので、フラグとして値を入力 Elseif Worksheets("sheet1").cells(i , 2).value > 30 then Range("A5")=Cells(i , 1) Range("B5")=Cells(i , 2) Exit for Endif if Worksheets("sheet1").Range("A5").value > 0 then Range("A6").Formula ="=(50-B5) / A5" Elseif Worksheets("sheet1").Range("A5").value = 0 then Range("A6") ="<30" Else Endif Next i End Sub >30だった項目の抽出まではできたのですが、計算値をだすところがどうしてもうまくいかず、A6セルにはどんな値でも”<30”と入力されてしまいます。 マクロの基本的なルールなどがまだまだ未熟なので、基本的な構文も書けていないと思います。 全然方向性が違うかもしれないので、そういった点も含めてご教示いただけたら幸いです。 分かりにくいかもしれませんが、どうぞよろしくお願いいたします。

  • ROUNDDOWNとIFの組合せでエラー表示になる

    数量×単価=の計算式で 数量が空白なら空白、そうでなければ数量×単価 で小数点切捨ての値が出るように作成しました。 ROUNDDOWN(IF(B27="","",B27*D27),0) 数量に値が入っている場合は問題ないのですが 数量が空白だと#VALUE!が表示されてしまいます。 どうすればエラー表示されなくなるのでしょうか?

専門家に質問してみよう