- 締切済み
エクセルVBAでテキストファイルを作ってセルを参照して置き換えしたい。
エクセル2000のVBAでテキストファイルを作ってセルを参照して置き換えしたいです。 1.元々同じ階層にtemplateというフォルダと、exceltest.xlsというエクセルファイルがあります。 更にtemplateフォルダの中にはtest3.sql、test4.sqlというテキストファイルがあります。 test3.sqlの内容 %野菜% %果物% %お菓子% test4.sqlの内容 %野菜% %果物% %お菓子% %野菜% %果物% %お菓子% %日本酒% %ワイン% exceltest.xlsの内容(6行目は見出し。データは7行目より。セルによってはデータが入っていない箇所もある。) A B C D E 1 2 3 4 5 6 野菜 果物 製菓 日本酒 ワイン 7 胡瓜 林檎 ガム 冷酒 赤 8 南瓜 葡萄 アメ 白 2.exceltest.xlsには実行ボタンが作ってあり、これを押すと以下の一連の作業を自動でするようにしたいです。 ・まず同じ階層に今日の日付名のフォルダが作られる。(例:20061127) ・そのフォルダの中に空の状態のtest1.sql、test2.sqlというテキストファイルが作成される。 ・エクセルデータが見出の下に何行あるのか数える。(今回の場合だと2行) ・その行数分test1.sqlにtest3.sqlのデータを書き込む。同様にtest2.sqlにはtest4.sqlのデータを書き込む。 更に、test1.sqlとtest2.sqlの文中の %お菓子% の文字をexceltest.xlsの製菓のデータの内容に置き換えたい。 同じように%ワイン%の文字をexceltest.xlsのワインのデータに、それぞれ置き換えたい。 一個目のデータには一行目のデータを、2個目のデータには2行目のデータを書き込みたいです。 以上よろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
みんなの回答
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。 >でもこんなに長くて難しい文ですと、上司に見られたらすぐに自分で作った物でない事がバレてしまいそうなので、自分でもちょこちょこ作ってみました。 今回は、私もいつも掲示板で書くスタイルとは変えています。いろんなことが見え隠れしているので、それを考えると、あまり手抜きは出来ないような気がしました。でも、それが、お役に立てなければ何もなりませんね。なお、関数やプロシージャは構造化されていますから、それらをバラバラにして、適当に組み合わせればよいです。 それと、たぶん、suzume_chuさんは、プロの世界の人でしょうね。VBAじゃ、いくら出来ても自慢にはなりませんね。だから、VB.Net なんかを勉強していますが、ついつい、こちらに手を出して、他のほうが何にも進んでいません。.Net Framework なんか使わなくても、なかなかのものが出来上がるのですが、いかんせん、Excel VBAじゃ、Access のように、ランタイムがあるわけではありませんし、どうしようもありません。 一応、もう出来上がっているとは思いますが、改編のポイント: 少なくとも、 '演算子を取り除く関数 というのは、こちらは状況が見えていないことと汎用性を考えて作っていますから、それはあまり必要がありません。 また、 '検索語のIndex を取り出す関数 は、ワークシートのMatch 関数を使うことが出来ます。 なお、 'スクリプトを取り出す関数 これは、省くことが出来ません。 >見ていただこうと思っていたのですが、 らしきものに作り変えますので、ご安心ください。 でも、私が、もしも同じような仕事をしている立場だとすると、「納期」の遅れが怖いです。いくら良いものが出来ても、「納期」に間に合わないと、すべてが、無に帰してしまいます。実は、失敗したことがあります。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。Wendy02です。 最初に、私は、Test1.sql,Test2.sql Perl などの言語と同じように、をスクリプトファイルと呼んでいますので、ご留意ください。 >他の%%のない箇所はそのままコピーするように言われました。 この意味を誤解していたりして、今、やっと最後の段階になって、意味を取り違えていたことに気づいてやり直しました。 >確かに%%が付かない箇所があります。 >他の%%のない箇所はそのままコピーするように言われました。 これも、二つの意味があると思い、それで、何度もやり直してしまいました。 >★※今の状態だと置換がまだ出来ていない状態。 >★※今の状態 この部分は、最初から、了解はしていましたが、これは、使っている本人がややこしいことになるのは承知だと思いますから、問題はないと思いますが、まったく最初の場合は、スクリプトの Test1.sql,Test2.sql は、出力されますが、 "二度目からは、こちらは出力されません。もし必要の場合は、コードの中で、上書きモードに変更しなければなりません。" なお、あらゆる場合を想定して、ユーザー定義関数は、かなり分けました。いずれは変更される可能性を予定しています。実は、このSQLのスクリプトファイル( Test1.sql, Test2.sql)は、意外に、様々な問題を残しているように思います。上司の方は、どう考えているか分かりませんが、VBAで加工する可能性を考えています。 Private Const DATA_COL As Integer = 5 'ワークシート側のタイトル数 '増やす場合は、ScriptMach 関数に行を入れる Private Const S1 As String = "お菓子" 'ワークシート側 Private Const R1 As String = "製菓" 'スクリプト側 Private Const SW_OVERWR As Boolean = False '上書きモード:オフ この部分で、細かな調整をしてくださるようにしました。 ただし、Test1.sql, Test2.sql のスクリプトファイルは、ご自身で書き換えてください。 また、多少の移植性は考えて、ワークシート関数には頼らないことにしました。ただ、VB.Net にするには、かなり無理があります。せいぜい、VB6 程度までです。ワークシートの部分は、Web コンポーネントや、テキストボックスでも、Rangeオブジェクトの部分を配列変数に入れることで対処できるはずです。 '----------------------------------------------------------- 'Option Explicit '予め設定しておいてください Private Const DATA_COL As Integer = 5 'ワークシート側のタイトル数 '増やす場合は、ScriptMach 関数に行を入れる Private Const S1 As String = "お菓子" 'ワークシート側 Private Const R1 As String = "製菓" 'スクリプト側 Private Const SW_OVERWR As Boolean = False '上書きモード:オフ Sub MakeFolderDateR3() 'Log:2564787, 2554584,2549512 Dim myDate As String Dim myPath As String Dim NewPath As String Dim Fno As Integer Dim ArScrFn(1) As String 'スクリプトファイル名 Dim ArFn(1) As String '出力ファイル名の配列 Dim i As Integer Dim sqlData(1) As String '配列 Dim cnt As Integer 'A7 以降の数を数える Dim rng As Range 'A6 からのデータ範囲(タイトル含む) Dim j As Integer Dim buf As String Dim mTitle1 As String Dim mTitle2 As String Dim myAr As Variant '配列に入れる ArFn(0) = "test1.sql" ArFn(1) = "test2.sql" 'スクリプトファイル名 ArScrFn(0) = "test3.sql" ArScrFn(1) = "test4.sql" 'データ 'test3.sql 'スクリプト sqlData(0) = "%野菜% %果物% %製菓%" 'test4.sql 'スクリプト sqlData(1) = "%野菜% %果物% %お菓子%" & vbCrLf & _ "%野菜% %果物% %お菓子%" & vbCrLf & _ "%日本酒% %ワイン%" 'アクティブシートにあるデータのA7から空白までの行数を数えて、その行数と同じ分、 With ActiveSheet '←コマンドボタンの場合はActiveSheetは必要ないはず Set rng = .Range("A6").CurrentRegion 'シートのチェックの為に 'If InStr(.Range("A6").Value, "野菜") = 0 Then MsgBox "シートが違うようです。": Exit Sub cnt = rng.Rows.Count 'データ行 End With If cnt = 0 Then MsgBox "ワークシートを確認してください。", vbInformation: Exit Sub 'ファイル名を作る myPath = ThisWorkbook.Path myDate = Format(Date, "yyyymmdd") NewPath = myPath & "\" & myDate '本日のパス名 'sql1,sql の出力 For i = 0 To 1 MakingScript sqlData(i), ArFn(i), NewPath, SW_OVERWR '上書きモードの時は、 SW_OVERWR =True Next i 'sql3, sql4 の出力 For i = 0 To 1 myAr = ReadScript(NewPath & "\" & ArFn(i)) MakingSQL rng, myAr, NewPath & "\" & ArScrFn(i) Next i End Sub Sub MakingScript(ByVal sqlData As Variant, ByVal oFileName As String, ByVal NewPath As String, Optional OverWrite As Boolean = False) 'sqlData:出力文字, oFileName:出力名,NewPath:日付パス,[OverWrite:上書きモード] Dim Fno As Integer If Dir(NewPath, 16) = "" Then 'vbDirectory MkDir NewPath End If '通常は、ファイルがない場合のみ書き換える If Dir(NewPath & "\" & oFileName) = "" Or OverWrite Then Fno = FreeFile() Open NewPath & "\" & oFileName For Output As #Fno Print #Fno, sqlData '出力も配列 Close #Fno End If End Sub Sub MakingSQL(myRng As Range, myAr As Variant, oFileName As String) 'myRng:ワークシートのデータ範囲, myAr:スクリプトの行ごとの配列変数 Dim myArRow As Variant 'スクリプトの行を切り分けた配列変数 Dim myArBuf As Variant Dim LastRow As Integer 'データの行数 Dim i As Integer Dim n As Integer Dim j As Integer Dim k As Integer Dim Ser As String '検索語 Dim buf As String Dim Fno As Integer If myRng.Columns.Count < DATA_COL Then MsgBox "データ個数が足りません", vbCritical: End LastRow = myRng.Rows.Count For n = 0 To UBound(myAr) myArRow = Split(myAr(n), " ", , vbTextCompare) ReDim myArBuf(UBound(myArRow)) For i = 2 To LastRow '注意:タイトル行は抜くので、2~ '問題はここ For j = 1 To UBound(myArRow) + 1 Ser = PickUpWord(myArRow(j - 1)) k = ScriptMatch(myRng.Rows(1).Cells, Ser) If k > 0 Then If myRng.Cells(i, k).Value <> "" Then '[品名] myArBuf(j - 1) = Replace(myArRow(j - 1), Ser, myRng.Cells(i, k).Value) Else 'セルが空の場合は、変換しない myArBuf(j - 1) = myArRow(j - 1) End If End If Next j If Len(buf) > 1 Then buf = buf & vbCrLf & Trim(Join(myArBuf, Chr(32))) 'スペースを区切り文字 Else buf = Trim(Join(myArBuf, Chr(32))) End If Next i Erase myArRow Next n Fno = FreeFile() Open oFileName For Output As #Fno Print #Fno, buf Close #Fno buf = "" End Sub Private Function PickUpWord(ByVal SearchWord As String) As String '演算子を取り除く関数 Dim Matches As Object ' Matches Dim Match As Object ' Match Dim buf As String Dim rep As String '演算子設定 Const OPE As String = "[\%\+\-\*\/]{0,1}" '使用させる演算子を入れる。ただし、手前に[\]を使う With CreateObject("VbScript.RegExp") .Pattern = OPE .Global = True .IgnoreCase = False Set Matches = .Execute(SearchWord) If Matches.Count > 0 Then buf = SearchWord For Each Match In Matches buf = Replace(buf, Match.Value, "") Next Match rep = buf Else rep = SearchWord End If End With PickUpWord = rep End Function Private Function ScriptMatch(TitleRng As Range, ByVal SearchWord As String) As Integer '検索語のIndex を取り出す関数 Dim c As Variant Dim i As Integer Dim flg As Boolean i = 1 '-------------------------------------------- '読み替え設定(必要な場合以下に入れる) 'モジュールレベル変数を使用する If InStr(SearchWord, S1) > 0 Then SearchWord = R1 '-------------------------------------------- For Each c In TitleRng If SearchWord Like "*" & c.Value & "*" Then ScriptMatch = i flg = True Exit Function End If i = i + 1 Next c If flg = False Then ScriptMatch = -1 End If End Function Private Function ReadScript(ByVal FileName As String) 'スクリプトを取り出す関数 Dim TextLine As String Dim myAr() As Variant Dim iFNo As Integer Dim buf As String Dim i As Long iFNo = FreeFile() Open FileName For Input As #iFNo Do While Not EOF(iFNo) Line Input #iFNo, TextLine If Len(Trim(TextLine)) > 2 Then ReDim Preserve myAr(i) myAr(i) = Trim(TextLine) i = i + 1 buf = "" End If Loop Close #iFNo ReadScript = myAr End Function
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。Wendy02です。 私は、やっていて、その考え方に気が付いたけのですが、この方法は、テキストストリーム型のPerlやSED などの、別の言語のやり方ですね。私はPerlは使いこなせないのですが、少しはやったことがあります。 それを、VBAで同じスタイルで作るというのは、私は、不勉強というか、なかなか難しいです。それでも、多少でも移植性を考えて置かないといけません。私の書いたものが理解して、編集してくださることが条件になりますが。あえて、Excelでなくても良いことも考えておいたほうがよい気がしました。 さて、遡って元の質問になりますが、SQLということは、 %野菜% %果物% %お菓子% % は、ワイルドカードのことですか? つまり、 ・ワイルドカードが付くときと、そうでないときがあるのではありませんか? また、どう考えても、以下の内容は、下のようになるような気がしてならないのですが、違いますか? ・一つ一つに置き換わっていくことと、 ・ブランクのものは、無視されるということ。 この二点が引っかかります。 以下は、現在のマクロの置き換わりのソーストの内容と結果です。 ************************************ ワークシートのセルの内容 ------------------------------------------- 野菜 果物 製菓 日本酒 ワイン ------------------------------------------- 胡瓜 林檎 ガム 冷酒 赤 南瓜 葡萄 アメ 白 ------------------------------------------- test4.sqlの内容 %野菜% %果物% %お菓子% %野菜% %果物% %お菓子% %日本酒% %ワイン% ↓ 最終的なtest2.sqlの内容 %胡瓜% %林檎% %ガム% %南瓜% %葡萄% %アメ% %胡瓜% %林檎% %ガム% %南瓜% %葡萄% %アメ% %冷酒% %赤% %白%
補足
Wendy02さん、回答どうもありがとうございます!本当に助かります。 これでまだ序の口だと思うと頭が痛いです・・・(^ー^;) ReadAllは別の言語でしたか・・・。失礼しました。 どおりでテキストに載ってないはずですね。別にReadAllには拘っていません。エクセルVBAであればOKです。 %%で囲ったのは何となくだと思います。上司がその場で考えてつけた印ですので。 このマークで囲った所が置き換えたい所、というしるしです。 確かに%%が付かない箇所があります。 他の%%のない箇所はそのままコピーするように言われました。 恐らく、その内全部の%%で囲った文字を置き換えるように言われるような気がします。 今日は以下の二点を指摘されました。 '★※今の状態だと置換がまだ出来ていない状態。 '★※今の状態 (SqlData(0) = SqlData(1) = の箇所。) だとtest3.sql、test4.sqlファイルのデータを変えたときにエラーがおきてしまうので、あくまでtemplateフォルダの中身を読み込む形で!と、言われました。 Private Sub CommandButton1_Click() Dim myDate As String Dim myPath As String Dim NewPath As String Dim FNo As Integer Dim Ar(1) As String Dim i As Integer Dim SqlData(1) As String Dim cnt As Integer Dim j As Integer Dim buf As String '配列に名前をつける Ar(0) = "test1.sql" Ar(1) = "test2.sql" '■↓ここをtemplateフォルダの中のtest3.sql、test4.sqlファイルを読み込む形に変えたいです。 SqlData(0) = "%野菜% %果物% %お菓子%" SqlData(1) = "%野菜% %果物% %お菓子%" & Chr(13) & Chr(10) & "%野菜% %果物% %お菓子%" & Chr(13) & Chr(10) & "%日本酒% %ワイン%" With ActiveSheet cnt = .Range("A7", .Range("A7").End(xlDown)).Rows.Count MsgBox (cnt) End With For i = 0 To UBound(SqlData()) ' buf = "" 'ループする際にデータが重複しないように""で消す。 For j = 1 To cnt buf = buf & SqlData(i) Next j SqlData(i) = Mid$(buf, 1, Len(buf) - 2) Next i myDate = Format(Date, "yyyymmdd") myPath = ThisWorkbook.Path NewPath = myPath & "\" & myDate '■ここに置換の式を入れる??replace?? 'パスの有無を調べる If Dir(NewPath, vbDirectory) = "" Then MkDir NewPath End If For i = 0 To UBound(Ar) FNo = FreeFile() Open NewPath & "\" & Ar(i) For Output As #FNo MsgBox SqlData(i) Print #FNo, SqlData(i) '出力も配列 Close #FNo Next i '終了メッセージ MsgBox f & "全ての作業が終了しました!" End Sub
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。Wendy02です。 ご事情は良く分かりました。 >「想定内」でしたか?! >実は上司から少しずつ作業をもらっているので、この先は私にはさっぱり分かりません(>_<) もしかして、上司の方は、これをしながら手順を教えているのと違いますか?あまりにも、インストラクティブ(教育的)なんですね。今やっていることは、まだ、序の口ですからね。この先、ややこしいものが入ってくるはずですね。^^;(早めに、なんとかしなくちゃね。本日できると思ったら、ダメでした。) 基本的には、いままでやったものは、コード自体は、あまり増やさないようにして、構造化させていかないといけません。このシリーズがもしも続くようなことがありましたら、もう一度、組み立てしなおさないといけないと思います。 前置きが長すぎて、肝心の内容ですが、 >ReadAllなどでtest3.sql, test4.sqlの内容を読んで、 という言葉に引きずられて、少し、自分の中で混乱してしまいました。 ReadAll ということは、 With CreateObject("Scripting.FileSystemObject") buf = .OpenTextFile(FileName).ReadAll 'Replace などを使って、置換していく End With ということですが、アイデアは良いと思ったのですが、今回は、基本的には行ごとに置換していくので、それをしてしまうと、全体が変わってしまいます。これでは、上手く行かないように思います。また、VBAですと、あえて、ストリームテキストを使うべきかどうかも、少し考える必要があります。今までのものを直して、それをしようとしたら、上手くないことに気が付きました。もし、考え方が違っていたら、ご指摘ください。なるべく早めに進めていきます。
- imogasi
- ベストアンサー率27% (4737/17069)
質問の意図が伝わりにくい。 「私ならこうする」という、好みもあろうが、質問を読んだ皆さんが、質問が判りづらくて、回答をパスしてないでしょうか。 >exceltest.xlsには実行ボタンが作ってあり、これを押すと以下の一連の作業を自動でするようにしたいです。 質問から省いても影響ないでしょう。これのコードもわからない? >フォルダが作られる 「フォルダを作る」と表現しては。 >テキストファイルが作成される 上記と同様、「テキストファイルを作成する」と表現しては? >何行あるのか数える 「行数分だけテキストファイルに書き込む」と表現しては? >「更に」「置き換えたい」 「置き換えたものを書き出す」で良いのでは。 「書き出す」フェーズと「置き換える」フェーズは別にしなければならない? 「書き込む」はレコードを最終の次ぎに「追加する」のこと? ??毎回(日)変わるのは、どのファイルのどこの項目?
補足
回答どうもありがとうございます。 >質問から省いても影響ないでしょう。これのコードもわからない? そうですね、省いても良かったかもしれません。コードは分かります。 分かりにくい文面で申し訳ありませんでした。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。Wendy02です。 お約束どおり、再び、戻って考えさせていただくことにしました。 回の質問を読ませていただきましたが、もう、ちょっと前のものの積み重ねがないと、他の回答者さんには難しいのではないか、と私は思いました。 個人的なことですが、私自身、いつまで、同じ内容の質問を見つけて追いかけて続けられるのか、ちょっと不安ですから、できれば、最長、3ヶ月ぐらいまでは、引っ張るだけ引っ張ってくださって結構です。継続が難しくなったら、こちらから書き込みいれます。 ただ、最初に、補足に書いていただいて、お礼側は、後にとっておいてください。お礼側が、メール送信されます。上手に使い分けてください。 それから、今回の質問は、「想定内」です。一番、最初から、そのような質問が出るというのは、最初のご質問から見えていました。^^;(実は、この先も見えているのですが、その先は、まったく自信がありません。谷尻かおりさんのテキストは持っているのですが、今まで、やってきていなかったので、これから勉強するつもりです。最近は、.Net に以降していくので、どうしても、そちらに重点が行ってしまっています。この一連の作業の流れは、たぶん、suzume_chuさんのご本業なのだと思いますが、この先、突っ込まれたら、どうしうか、と思っているしだいです。今、やっているのは、まだ、入り口でしょうね。) さて、元のご質問に戻りますが、作業の流れが少し見えてきません。もう一度、こちらから流れを確認させていただきます。 (済)1.まず同じ階層に今日の日付名のフォルダが作られる。(例:20061127) ↓ ×#2.そのフォルダの中に空の状態のtest1.sql、test2.sqlというテキストファイルが作成される。 これをすると、二度手間になってしまいます。 #3.エクセルデータが見出の下に何行あるのか数える。(今回の場合だと2行)+その行数分test1.sqlにtest3.sqlのデータを書き込む。//同様にtest2.sqlにはtest4.sqlのデータを書き込む。 -------------------------------------------------------- (まだ、コードとしては試験していませんから、変わる可能性があります) ということは、言い換えると、 N3. test3.sql, test4.sql を作っておいて、それをcopy で、test1.sql, test2.sql を作っておいて、 N4. Append モードで、以下を書き込む、ということになるのではないでしょうか? ------------------------------------------------------ N4.-2 更に、test1.sqlとtest2.sql の文中の %お菓子% の文字をexceltest.xlsの製菓のデータの内容に置き換えたい。 同じように%ワイン%の文字をexceltest.xlsのワインのデータに、それぞれ置き換えたい。 ------------------------------------------------------- N4-2.そのものについては、特に問題はないと思います。(Nは、New のNです) ただ、その内容が、test3.sql と test4.sql の違いは、どういうロジックなのですか? 6 野菜 果物 製菓 日本酒 ワイン '(製菓→お菓子) ↓ -------------------------------------- > test3.sqlの内容 > >%野菜% %果物% %お菓子% ===================================== >test4.sqlの内容 > >%野菜% %果物% %お菓子% >%野菜% %果物% %お菓子% >%日本酒% %ワイン% -------------------------------------- 結果としては、 test3.sqlの内容 は、 %胡瓜% %林檎% %ガム% %南瓜% %葡萄% %アメ% test4.sqlの内容 %胡瓜% %林檎% %ガム% %胡瓜% %林檎% %ガム% %冷酒% %赤% %南瓜% %葡萄% %アメ% %南瓜% %葡萄% %アメ% %% %白% ということになってしまうように思います。実にややこしいです。
補足
Wendy02さん、回答どうもありがとうございます!! 「想定内」でしたか?! 実は上司から少しずつ作業をもらっているので、この先は私にはさっぱり分かりません(>_<) N3. もともとtest3.sql, test4.sql は用意してあります。 イメージとしてはReadAllなどでtest3.sql, test4.sqlの内容を読んで、それをエクセルの行数分test1.sql、test2.sqlにコピーする時にReplaceもすませたいです。 製菓とお菓子はテキストとエクセルでは微妙に項目名が違ったりしているので違う名前で書きました。 >test3.sql と test4.sql の違いは、どういうロジックなのですか? 実は私もこの後これをどう使うかや元々どういったデータなのか分からず作っているので不透明なのですが、重複している項目があったり、新しい項目があったりと、サンプルで作った物と近い状態です。 最初もっと細かく書いたのですが、質問が800文字までだったので削除しました。 以下が最終的なファイルの内容です。 最終的なtest1.sqlの内容 %野菜% %果物% ガム %野菜% %果物% アメ 最終的なtest2.sqlの内容 %野菜% %果物% ガム %野菜% %果物% ガム %日本酒% 赤 %野菜% %果物% チョコ %野菜% %果物% チョコ %日本酒% 白 拙い文で申し訳ありませんが、どうぞよろしくお願いします。
補足
Wendy02さん、丁寧な回答本当にどうもありがとうございます! そして、会社ではサイトの規制があって書き込みが出来ず、お礼が遅れて申し訳ありませんでした。 昨日から、書いていただいたプログラムを実際の業務データに使えるように書き換えて試しています。 でもこんなに長くて難しい文ですと、上司に見られたらすぐに自分で作った物でない事がバレてしまいそうなので、自分でもちょこちょこ作ってみました。 とりあえず置き換えがどうしても出来ないのですが、それっぽいものが出来ました。 見ていただこうと思っていたのですが、今日はコピーして家にメールを送るのを忘れてしまいました。 また後日補足に載せます。 こんなに面倒な質問に丁寧に答えていただいて、本当に感謝しています。ありがとうございます。