[[20130702195901]] 『EXCEL2000→EXCEL2003へ変えたらマクロが動きませ』(代理人) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『EXCEL2000→EXCEL2003へ変えたらマクロが動きません』(代理人)

 久方ぶりに門を叩かせていただきます。

 EXCEL2000(Windows2000)で作成したマクロが、EXCEL2003(Windows7)マシンに変わったら途中でエラーになってしまいます。
 事例を挙げさせていただきますと、

 Range("A1").AutoFilter Field:=7, Criteria1:="3"
 Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).XlBorderWeight = xlHairline

 上記下段でエラーとなり
 "実行時エラー '-2147417848 (80010108)':"
 "'Weight'メソッドは失敗しました: 'Border' オブジェクト"
 と表示されます。

 試しに Weight を xlBorderWeight に書き換えて実行すると、今度は
 "実行時エラー '1004':"
 "RangeクラスのCurrentRegionプロパティを取得できません。"
 と言われてしまいます。

 大した処理をやってもないのに、エラーとなった後はマシンの挙動もおかしく
 EXCELウィンドウを閉じてもお化けEXCELウィンドウが残り消えず、やむなく
 タスクマネージャで消すという状態です。

 他にもNewマシンにも関わらず処理時間が5倍以上遅くなるなど、困ったことに
 なっています。

 というわけで、上記エラーの解決方法につきご教授いただけませんか。
 よろしくお願い致します。

EXCEL2003(Windows7)


以下は2000と2010で動作しました。2003でも動きそうに思います。
Range("A1").AutoFilter Field:=7, Criteria1:="3"
Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).Weight = xlHairline

2000と2003を同じフォルダにインストールしてしまい、おかしくなっていませんか?
同居の場合は、インストール時に \Office2003\ 等の異なる名前にしておくのが安全です。
セットアップを右クリックし、管理者権限による2003の再インストールをお薦めします。
(???)


???様 

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

 こちらのマクロ稼動環境をご説明します。
 EXCEL2000のクライアントPCで作成したマクロが共有サーバーに置かれており、クライアントPCからマクロを都度サーバーから呼び出してきて、クライアントPC上で起動させています。
 先日クライアントPCをEXCEL2003(Windows7)搭載PCに新調し、上記同様のやり方でマクロを起動した時エラーが発生したという状況です。
 なのでPCの同じフォルダ内にEXCEL2000とEXCEL2003がインストールされているわけではありません。

 ご推測の通り、確かにエラーにならず動くマクロもあります。
 ので、何が悪さしてエラーになってしまうのか、よくわかりません。

 何かお知恵がありましたら、引き続きご教授いただけますようお願いいたします。

(代理人)


同居の可能性は無いならば、インストール問題では無さそうですね。

2000と2003でマクロ動作が違うとは思えないので、そうなるとOSの違いが気になります。
目的のブックをWIN7の新PCにコピーし、ローカルで実行するとどうなるでしょう?
(???)


 環境を変え、よくわからないエラーが出る場合、
 参照設定に「参照不可」がないか確認してみてください。
 (cai)

「EXCEL2000のクライアントPCで作成したマクロが共有サーバーに置かれており、クライアントPCからマクロを都度サーバーから呼び出してきて、…」

この部分も気になりますね。ローカルに全て置くと動く場合、具体的にマクロはどう置いていて、
どう読み込んでいるかを教えてください。マクロはテキストファイルになっていて、それを
VBProjectに読み込んでいる、等。
(???)


???様

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

 >2000と2003でマクロ動作が違うとは思えないのでそうなるとOSの違いが気になります。目的のブックをWIN7の新PCにコピーし、ローカルで実行するとどうなるでしょう?

 サーバに置かれたマクロはEXCELブック形式で保管されており、クライアントPCのEXCELに設定したボタンを押下することで、そのブックのmainマクロを起動しています。
 ご提案通りそのブックを新PCローカルにコピーし起動しましたが、結果同じエラーでした。

cai様

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

 知識が無く"参照設定"の確認方法がわかりません。どこをどう見れば確認できますでしょうか。教えていただければ幸いです。

 お手数をお掛けしますが、引き続きご教授いただけますようお願いいたします。


クライアントPCのブックは、サーバ上のブックをOpenしているだけであり、サーバ上のブックで
Auto_Openに記述したマクロが動く、という事でしょうか。それとも、サーバのブックを開いた後、
クライアントブックからサーバブックの独自名マクロを呼び出しているのでしょうか。

開き方はどうあれ、オートメーションエラーでハングアップ状態になるのは、特定OS+IEの環境で
他ブック上のセルを何万回もコピペした場合とか、サーバ上のブックが壊れている場合と思います。

今度は、新しいブックに全シートと標準モジュールをコピーし、動かしてみてください。
(???)


???様

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

 まず、お問い合わせのマクロ呼び出し方法ですが、ユーザー設定ボタンのマクロ登録欄にサーバ内ブックのパスと起動させる特定マクロ名を登録しており、それを押下しています。
 恐らく"サーバのブックを開いた後、クライアントブックからサーバブックの独自名マクロを呼び出している"ことになるかと思います。

 ご指示の通り、新ブックにマクロブック内シートをコピーし、標準モジュールを挿入しマクロコードを全てコピペし、起動してみましたが、結果は同じエラーでした。

 エラーとなった時の処理シートですが、ヘンテコになってます。
 エラー直前行のAutofilterが正しく掛かった状態で、なぜかA列の2行目以降のみが選択されたような太枠で囲まれており、これも913行目以降からは行ナンバーエリア側へ一桁分くらい左に寄って(A列の値の一桁目に枠が重なって)見えたりしています。データ件数は4000件弱なんですが、枠は延々と下に延び、スクロールバーを最下部まで下げて(11000行あたり)も、さらに下へスクロールするとまだ続いている様子。どこかのセルにカーソルを置いてもその選択枠らしきものは消えません。
 それゆえEXCELを閉じようとしてもお化けが出てしまうんでしょうね。

 お手数をお掛けしますが、引き続きご教授いただけますようお願いいたします。

(代理人)


 すでに確認済と思いますが、参照設定はVBEの ツール(T) にあります。
 (cai)

ブックが壊れているわけでも無かったですか。参照設定の問題も、シートとモジュールを
コピーしても直らないところをみると、無関係のように思えます。
(サーバブックとクライアントブックで作成バージョンが違っている、とかは無いですよね?)

次は、Excelの不具合を疑ってみます。元のマクロで、CurrentRegionとSpecialCellsを
併用していますが、これはどちらも範囲選択を伴うので、似た機能の重複になっています。
これと他ブックでのマクロ実行が重なり、想定外の使い方となって問題が出ている可能性です。

どちらか一方だけでも結果は変わらないと思うので、試してみてください。
(一発で解決できなくて申し訳ないのですが、こちらでは現象を再現できないもので…)

Range("A1").CurrentRegion.Borders(xlEdgeBottom).Weight = xlHairline
または、
Range("A1").SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).Weight = xlHairline

(???)


???様

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

 ご提案の対策早速やってみました。

 Range("A1").CurrentRegion.Borders(xlEdgeBottom).Weight = xlHairline 
 →  "実行時エラー '-2147417848 (80010108)':"
     "'Weight'メソッドは失敗しました: 'Border' オブジェクト"
 Range("A1").SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).Weight = xlHairline 
 →  "実行時エラー '1004':"
     "RangeクラスのSpecialCellsプロパティを取得できません。"
 と残念な結果でした。

 新PCに変えてから、セキュリティが高まったのか(EXCELのセキュリティレベルは最低にしてます)
処理が非常に遅く、内部的にチェックなどを行って(オプションで自動チェックは外してます)リソースがなくなっての現象なんでしょうか。
 あるいはエラー部の前で、EXCEL2000時からは変わった古いコマンドが使われていて、内部的におかしくなるとか・・・。 素人考えですが。

cai様

 ご連絡ありがとうございました。
 確認したところ、参照可能なライブラリとして以下3点にレ点がついた状態です。
 Visual Basic For Applications
 Microsoft Excel 11.0 Object Library
 OLE Automation

 お手数をお掛けしますが、引き続きご教授いただけますようお願いいたします。


命令を削っても、元々のエラーと変わらない症状ですね。何故だろう?

実際のサーバブックも、Range("A1")のようにブック名を省略していますか?
ブック名シート名を明記するようにしてみてください。
(ブック名の問題ならば、2000を使っていたときも同じになっていたはずなので、
関係ないと思うのですが…)

Workbooks("Book1.xls").Sheets("Sheet1").Range("A1").AutoFilter Field:=7, Criteria1:="3"
Workbooks("Book1.xls").Sheets("Sheet1").Range("A1").CurrentRegion.Borders(xlEdgeBottom).Weight = xlHairline

(???)


???様

 何度もご返答いただきありがとうございます。

 早速やってみました。
 Workbooks("T_S.txt").Sheets("T_S").Range("A1").AutoFilter Field:=7, Criteria1:="3"
 Workbooks("T_S.txt").Sheets("T_S").Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).Weight = xlHairline

 下段でエラーとなり停止しました。(上段はOK)
 "実行時エラー '-2147417848 (80010108)':"
 "'Weight'メソッドは失敗しました: 'Border' オブジェクト"

 何もせず 再起動すると、今度は
 "実行時エラー '1004':"
 "RangeクラスのCurrentRegionプロパティを取得できません。"
 となりました。あとは何度やっても上記メッセージでした。

 お手数をお掛けし大変恐縮ですが、、引き続きご教授いただけますようお願いいたします。
 (代理人)
 

ブック名を明示しても、エラーが変わりませんね。ん、ブック名がT_S.txt?
ファイル名が「T_S.txt.xls」なのでしょうか? それとも、サーバのブックが更に
テキストファイルを開いている? その辺りの仕組みを教えてください。

または、実は現在のデータに問題がある可能性はないでしょうか?
過去動いていたデータを使ってみるか、他の人のExcel2000環境で動かしてみるとか。
(???)


???様

 何度もご返答いただきありがとうございます。

 データに問題がないか・・・とのことでした。
 "サーバのブック"はマクロ(と処理で必要となる原単位データシート)を保管しているだけです。
 そのマクロが、IBM AS/400内にあるデータを切り取るSQL定義ファイルを起動し、テキストファイルで一旦共有サーバ内に取り込み、これを更に加工しています。

 この仕組みは、マクロを作成した5年以上前から変わっていないので、取り込んだテキストデータがおかしいことは考えにくいと思ってます。現に同じ仕組みの別マクロは、新調PCでも問題なく動くものもありますし。
 試しに取り込むデータ形式をEXCEL形式にしてみましたが、結果は同じでした。
 EXCEL2000(Windows2000)であれば、問題なく動きます。

 なかなか解決できず大変恐縮ですが、他に何かしら手掛かりなどありましたら、引き続きご教授いただけますようお願いいたします。
 (代理人)


なるほど、データの問題である可能性は少なそうですね。
範囲選択し罫線を描くマクロなので、途中に抜けがあったりして範囲選択が
思ったようにできていない可能性を考えていました。関係なさそうです。

もしあるとすれば、データ量が増えてきたために、Excelの問題にかかって
しまった可能性。しかし、これはむしろメモリリーク問題のあるExcel2000の
方が問題になると思われるので、これも違いますね。

クライアントブックは、サーバブックのマクロを起動するとの事ですが、
それはDBアクセスを伴うマクロも起動していますか? 原因追求は諦めて、
現在サーバブックで行われている事を、全てクライアントブック1つで
済ませてしまう変更案もあるかと思います。
(???)


???様

 何度も何度もご返答いただきありがとうございます。

 "もしあるとすれば、データ量が増えてきたために、Excelの問題にかかってしまった可能性。"
 当方の印象ではこれではないかと思います。EXCEL2003あるいはWindows7になり、 
EXCEL内部でEXCEL2000時にはなかった処理が走って、メモリなどリソースを多く使用してしまっているのではと。
 それで, 上段の"Range("A1").AutoFilter Field:=7, Criteria1:="3"" を実行した所で
余力がなくなり、EXCEL画面上でカーソルでセルが選べないなど通常の動作が効かない
とか、マクロ内で"Range"指定を認識できなくなり、"Range"にかかる"Wight"や"CurrentRegion",
"SpecialCells"などが認識できないような気がしてます。これは何ともしようがないものなのでしょうか。

 "クライアントブックは、サーバブックのマクロを起動するとの事ですが、
それはDBアクセスを伴うマクロも起動していますか?"
 DBアクセスは、AS/400のファイル転送ユーティリティ実行ファイルを
CreateObject("WScript.Shell")でRUNさせるだけで、あとは触りには行きません。

 "現在サーバブックで行われている事を、全てクライアントブック1つで済ませてしまう
変更案もあるかと思います。"
 これはマクロをサーバブックでなくクライアントブックで持って起動するという意味でしょうか。
 現在サーバブックをボタンで起動すると、サーバブックをクライアントPC上でOPENし、
指定のマクロを起動しているので、基本クライアントPCで全て処理しています。
マクロをクライアント側ブックで保管しても同じ結果のような気がしてます。

 なかなか解決できず大変恐縮ですが、他に何かしら手掛かりなどありましたら、
引き続きご教授いただけますようお願いいたします。
 (代理人)

クライアントブックの元マクロ自身がDBアクセスせず、サーバブック上で動いているところが不安。
全部クライアントブックに変えてみれば、というのは、DB処理をOLE経由せず自ブック内で動かすこと。
普通はExcelの限界を超えて範囲指定や罫線を引いてもエラーになるだけであり、ハングアップまで
いくきっかけとして、他ブックでDBアクセスは怪しいと思います。

試しに、DBアクセスして最新データを持ってくる部分を動かさず、残っている過去データで
範囲指定と罫線のマクロだけ動作させると、データが多くても普通に動いたりしませんか?

他ブックでのDBアクセスの問題なのか、範囲選択の問題なのか、罫線指定の問題なのかを切り分けてみてください。
(???)


???様

 何度も何度もご返答いただきありがとうございます。

 ご提案の切り分けやってみました。
 "試しに、DBアクセスして最新データを持ってくる部分を動かさず、残っている過去データで 
範囲指定と罫線のマクロだけ動作させると、データが多くても普通に動いたりしませんか?"
 →最新データ取り込みはせず、共有サーバに残った前回取り込みデータをOPENし加工してみま
したが、残念ながら結果は同じでした。

 次に、罫線の問題を問うため、NG行(下段)の前に仮の
"Range("A1:AQ1").Borders(xlEdgeBottom).Weight = xlMedium" なるダミー行を入れた所、
なぜか、NG行を通過できました!!!
で、さらに下部にある
 "Range("A1").CurrentRegion.Borders(xlInsideVertical).LineStyle = xlDot" にてNGとなり、
 "実行時エラー '-2147417848 (80010108)':"
 "'LineStyle'メソッドは失敗しました: 'Border' オブジェクト"が表示されました。
 →上記に習い、"Range("A1:AQ1").Borders(xlInsideVertical).LineStyle = xlDot" を直前に
 入れてみましたが、今度はうまくいかず再びエラーで停止しました。

以上のことから、何かわかりますでしょうか。
(代理人)


DBアクセス部分抜きでも再現ですか。予想をことごとく外してますね…。

ダミー行で通ったのは、範囲選択を明示的に行ったおかげ?
CurrentRegion等の自動範囲選択をやめて、明示的に変えて試してみてください。

 Sub test()
    Dim iC As Long
    Dim iR As Long
    Dim cw As String

    iC = Cells(1, Columns.Count).End(xlToLeft).Column
    iR = Cells(Rows.Count, "A").End(xlUp).Row
    cw = "A1:" & Cells(iR, iC).Address

    Range("A1").AutoFilter Field:=7, Criteria1:="3"
    Range(cw).Borders(xlEdgeBottom).Weight = xlHairline
End Sub
(???)

???様

 何度も何度もご返答いただきありがとうございます。

 ご提示のロジック、そのまま挿入しやってみたら、NGでした。当方も行けると思ったんですが。
 ただ同じ"Weight"のエラーでも、"失敗しました"ではなく
 "実行時エラー '1004':"
 "BorderクラスのWeightプロパティを設定できません。" でした。

 でも提示ロジックになかったSpecialCells(xlCellTypeVisible)を入れて実行したら、
 "実行時エラー '-2147417848 (80010108)':"
 "失敗しました"と言われました。

 選択範囲を明示しただけではダメなようですね。
 なぜあのダミー行が入ると自動範囲選択が通るんでしょうか?
 謎は深まるばかりです。

(代理人)


先のコーディングで、iCやiR、またはcwの変数はどのような値だったでしょう?

データが増えて範囲が広くなって問題がでているならば、Excel2003で処理するには
1行ずつループし、Visibleな行のみ1行ずつ罫線を引いていくよう修正しないと
いけないように思います。
(???)


???様

 何度も何度もご返答いただきありがとうございます。

 "先のコーディングで、iCやiR、またはcwの変数はどのような値だったでしょう?"
 → 各値は iC=139, iR=3685, cw="A1:$EI$3685" で、正しくシートデータの値を拾っています。
 データ量は問題となるほどの量ではありませんし、日々増減など変動はあるかと思いますが、
今回のロジックであれば正しく指定することができます。

 ダミー行挿入でNG解消できないか、2回目のNGとなる
 "Range("A1").CurrentRegion.Borders(xlInsideVertical).LineStyle = xlDot"
 の前にいろいろ入れてみて、傾向を探りましたがなかなかOKとなりません。
 入れてみたダミー行
 ・Range("A1").Select
 ・Range("A1:AQ2").Borders(xlInsideVertical).LineStyle = xlContinuous
 ・Range("A1:AQ1").Borders(xlEdgeBottom).Weight = xlMedium
 ・Range("I2:AQ" & in1end * 3 - 2 & "").Borders(xlInsideVertical).LineStyle = xlDot

 なかなか解決できず大変恐縮ですが、他に何かしら手掛かりなどありましたら、
引き続きご教授いただけますようお願いいたします。
 (代理人)


結構多いセル範囲だと思います。50万セル以上ありますよ。
原因は、Excelのメモリ管理の問題かも知れません。とりあえず、範囲選択後に、
元のデータより下まで範囲とした1本線を描いておくと、それよりも内側の描画が
成功するようです。(厳密には先の変更時に使用した変数iR+1か)

Range("A1").AutoFilter Field:=7, Criteria1:="3"
Range("A1:EI4000").Borders(xlEdgeBottom).Weight = xlHairline
Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Borders(xlEdgeBottom).Weight = xlHairline
(???)


???様

 何度も何度もご返答いただきありがとうございます。

 "原因は、Excelのメモリ管理の問題かも知れません。"に何か光が見えた気がします。

 が、肝心の
 "Range("A1:EI4000").Borders(xlEdgeBottom).Weight = xlHairline" が
 "実行時エラー '-2147417848 (80010108)':"となってしまいました。
 ので、命令文を変更し、
 "Range("A4000:EI4000").Borders(xlEdgeBottom).Weight = xlHairline" で何とか4000行に
 線が引けたのですが、例のNG文でエラーとなってしまいました。(xlMediumでもだめ)
 非常に悩ましいです。

 取り急ぎ結果報告いたします。
 (代理人)


Range("A4000:EI4000")だと、選択範囲が1行です。複数行で試してみてください。

メモリ問題だとして、直前に大きな範囲指定することで大きな領域が確保され、
その後の小さな領域がちゃんと動くかも…、といったところです。
数行範囲選択するだけでは足りないと思います。

あと、最初はAutoFilterより前にダミー範囲選択を入れたのですが、これは
Excel2000でアプリケーションエラーとなったので、AutoFilterの後にしました。
データ内容でも変わってきそうです。
(???)


1行ずつ線を引く例。
Excelの動きが怪しいので、このようにメモリを使わない対策を行うのが良いかと。

 Sub test()
    Dim i As Long
    Dim iC As Long
    Dim iR As Long
    Dim iFlag As Long

    iC = Cells(1, Columns.Count).End(xlToLeft).Column
    iR = Cells(Rows.Count, "A").End(xlUp).Row

    For i = 2 To iR + 1
        If Cells(i, 7).Value = 3 Then
            iFlag = iFlag + 1
        Else
            If 0 < iFlag Then
                Range(Cells(i - 1, 1), Cells(i - 1, iC)).Borders(xlEdgeBottom).Weight = xlHairline
                iFlag = 0
            End If
        End If
    Next i

    Range("A1").AutoFilter Field:=7, Criteria1:="3"
End Sub

(???)


???様

 何度も何度もご返答いただきありがとうございます。

 "Range("A1:EI4000").Borders(xlEdgeBottom).Weight = xlMedium"を直前に挿入したら通りました!

 ただ下にある "Range("A1").CurrentRegion.Borders(xlInsideVertical).LineStyle = xlDot"で
 エラーとなりました。
 なので、同様に"Range("A1:EI4000").Borders(xlEdgeBottom).Weight = xlMedium"を直前に挿入
 してみましたが、この文でエラーになります。
 直前で"Range("A1").AutoFilter"とクリアしているのが何か影響でも?

 取り急ぎ結果報告です。

 FOR〜NEXT文はやってみます
(代理人)

縦線は、フィルタする前に全行に引いてしまっては駄目ですかね?
(???)

???様

 本日より別業務優先となり、レスができずすみませんでした。

 お伝えしておりませんでしたが、ひとつこのマクロで不可解なことがあります。
 このシートは1〜31日のエリアを列方向にいくつか持って、日当たりの計画を多項目にて
 把握しています(故に139列もある)。
 それぞれにて、1データづつ1日〜前日までの日当たりの計画・実績の累計差も計算しています。

 不可解点:当日が28日以降の日付になるとエラーになる。27日以前であれば通常終了できる。

 これまで当日を6/28としてエラーを出しておりましたが、今日別の人が本日分のリストを作成
 すべく7/10で処理すると、問題なくできてしまいます。28〜31日分ができなくて困って
 いる状況です。
 行・列はほぼ毎日同一なので、これはやはりメモリ管理の問題でしょうか。

 報告1:"縦線は、フィルタする前に全行に引いてしまっては駄目ですかね?"
 "Range("A1").AutoFilter Field:=7, Criteria1:="3"" の前に
 "Range("A1").CurrentRegion.Borders(xlInsideVertical).LineStyle = xlDot"
 を挿入してみましたがエラーでした。

 報告2:"1行ずつ線を引く例"
 毎度止まってしまう後半の縦線部を一行づつでトライしました。
 iC = Cells(1, Columns.Count).End(xlToLeft).Column
 iR = Cells(Rows.Count, "A").End(xlUp).Row
 For i = 1 To iC
     Range(Cells(1, i), Cells(iR, i)).Borders(xlEdgeLeft).LineStyle = xlDot
 Next i
 こちらもエラーでした。

 いかがでしょうか。
(代理人)

データ量で動いたり動かなかったり、やはりメモリが関係していそうです。
だからデータ量が増えたときにおかしな現象になるのでしょう。

Excel2000で実験しても、データ量が多い場合にエラーになりますので、動いていたのは
たまたまかと思われます。

範囲選択を止めて、縦線も横線も1行ずつ描くようにするのをお薦めします。

 Sub test()
    Dim i As Long
    Dim iC As Long
    Dim iR As Long
    Dim iFlag As Long
    Dim iSt As Long

    iC = Cells(1, Columns.Count).End(xlToLeft).Column
    iR = Cells(Rows.Count, "A").End(xlUp).Row

    For i = 2 To iR + 1
        If Cells(i, 7).Value = 3 Then
            If iFlag = 0 Then
                iSt = i
            End If
            iFlag = iFlag + 1
        Else
            If 0 < iFlag Then
                Range(Cells(iSt, 1), Cells(i - 1, iC)).Borders(xlInsideVertical).LineStyle = xlDot
                Range(Cells(i - 1, 1), Cells(i - 1, iC)).Borders(xlEdgeBottom).Weight = xlHairline
                iFlag = 0
            End If
        End If
    Next i

    Range("A1").AutoFilter Field:=7, Criteria1:="3"
End Sub
(???)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.