advanced help
per page, with , order by , clip by
Results of 1 - 1 of about 295 for cell filename (0.001 sec.)
cell (1170), filename (1984)
[[20230620143850]]
#score: 11157
@digest: fd9646d9dca26af7934603e0e14ec12e
@id: 94521
@mdate: 2023-06-23T00:36:14Z
@size: 22459
@type: text/plain
#keywords: joinsh (55081), 合シ (44371), 方") (38086), 統合 (26353), shcount (22848), maxcol (21703), 四方 (20367), myarray (19729), srcrng (17503), 業担 (16856), dstrng (15352), 合" (14581), maxrow (11361), searchdirection (9228), xlformulas (8086), xlprevious (7557), searchorder (7313), 営業 (6140), filename (6041), parent (4635), worksheets (4531), 終列 (4183), シー (3765), ート (3109), 最終 (3059), cells (2858), 終行 (2788), ル→ (2450), 取得 (2296), 2023 (2108), 担当 (1981), thisworkbook (1919)
『複数シートの統合』(マクロって難しい)
よろしくお願いいたします。 個々の営業担当が持っている案件管理のエクセルデータを ひとつのシートにまとめて売上の見込みを集計したいのです。 個々の営業のファイルとデータ統合用のファイルは一つのフォルダに入れています。 私はマクロはほとんどわかりません。 ネットで調べてコードをコピーさせてもらうのがほとんどで 今回、下記のマクロを使っています。問題なく動きます。 3つ追加・変更したい内容があるのですが どこをどう触ればいいのかわかりません どなたかお分かりの方教えてください。 (1)営業さんの中には自分の作業や管理用に別のシートを追加しておられる方がいます。シートを読み込む際に各ファイルの一番左のシートのみを読み込みたいです (2)各営業のファイルのシート名は営業担当の名前になっています。 統合した際にA列にシート名(=営業担当者名)を入れたいです (3)前回データの削除マクロは私が後からマクロの記録で追加したものです。 同じエクセルで定期的にデータを統合するので先に前回のデータをクリアしようとしたものです。 Sheets(Array("一山", "二階堂", "三田", "四方")).Select Sheets("四方").Activate ActiveWindow.SelectedSheets.Delete 営業担当は頻繁に入れ替わるのでこの部分を4人のシートという意味ではなく、一番左の統合シート以外のシートをすべて削除にしたいです どうぞよろしくお願いします。 参考にしたサイト:https://officedic.com/excel-vba-join-worksheetsdata/ *************************************** Sub 案件管理表の統合() Call 前回データの削除 Call シートの読み込み Call データの統合 End Sub Private Sub 前回データの削除() Sheets("統合").Select Cells.Select Selection.ClearContents Sheets(Array("一山", "二階堂", "三田", "四方")).Select Sheets("四方").Activate ActiveWindow.SelectedSheets.Delete End Sub Private Sub シートの読み込み() Dim Filename As String Dim IsBookOpen As Boolean Dim OpenBook As Workbook Dim ShCount As Long With CreateObject("WScript.Shell") .CurrentDirectory = "C:¥Users¥Desktop¥営業案件管理¥" 'ここで読み込むフォルダを直接指定する" End With Filename = Dir("*.xlsx") Do While Filename <> "" If Filename <> ThisWorkbook.Name Then IsBookOpen = False For Each OpenBook In Workbooks If OpenBook.Name = Filename Then IsBookOpen = True Exit For End If Next If IsBookOpen = False Then ShCount = ThisWorkbook.Worksheets.Count Workbooks.Open (Filename), UpdateLinks:=1 Worksheets.Copy after:=ThisWorkbook.Worksheets(ShCount) Workbooks(Filename).Close savechanges:=False End If End If Filename = Dir() Loop End Sub Private Sub データの統合() Dim i As Long Dim r As Long Dim s As Long Dim Sh As Worksheet Dim MaxRow As Long Dim MaxCol As Long Dim MyArray As Variant Dim JoinSh As Worksheet Application.DisplayAlerts = False 'シート削除時のアラート停止 For Each Sh In Worksheets If InStr(Sh.Name, "統合") <> 0 Then Sh.Delete 'すでに統合シートが存在する場合は一旦削除 Next Application.DisplayAlerts = True 'シート削除時のアラート停止を解除 s = 1 '最大行を超えた場合次の統合シートを作成するための番号 Worksheets.Add Before:=Worksheets(s) '新規に統合シートを追加 ActiveSheet.Name = "統合" Set JoinSh = ActiveSheet '統合シートを変数に格納 For i = s + 1 To Worksheets.Count 'シートを統合シートの次〜末尾までループ With Worksheets(i) '各月シート If i = 2 Then r = 1 '最初だけ項目も取得 Else r = 2 '最初以外は2行目から取得 End If MaxRow = .Cells(Rows.Count, 1).End(xlUp).Row '1列目で最終行を取得 MaxCol = .Cells(1, Columns.Count).End(xlToLeft).Column '1行目で最終列を取得 MyArray = Range(.Cells(r, 1), .Cells(MaxRow, MaxCol)) 'A1〜データ末尾まで配列に格納 End With With JoinSh '統合シート MaxRow = .Cells(Rows.Count, 1).End(xlUp).Row '統合シートの1列目で最終行取得 If MaxRow + UBound(MyArray) > Rows.Count Then '最大行を超える場合の処理 s = s + 1 '統合シートの番号を加算 Worksheets.Add Before:=Worksheets(s) '新規に統合シートを追加 ActiveSheet.Name = "統合" & s '名前が同じにならないように番号を追加 Set JoinSh = ActiveSheet '統合シートを変数に格納 MaxRow = JoinSh.Cells(Rows.Count, 1).End(xlUp).Row '統合シートの1列目で最終行取得 End If If .Cells(1, 1) = "" Then '最初だけ1行目から貼り付け Range(.Cells(1, 1), .Cells(UBound(MyArray), MaxCol)) = MyArray Else '最初以外は最終行の次に貼り付け Range(.Cells(MaxRow + 1, 1), .Cells(MaxRow + UBound(MyArray), MaxCol)) = MyArray End If End With Next i End Sub < 使用 Excel:Excel2016、使用 OS:Windows10 > ---- たとえば... (1) ' Worksheets.Copy after:=ThisWorkbook.Worksheets(ShCount) ↓こっちに変更 Worksheets(1).Copy after:=ThisWorkbook.Worksheets(ShCount) (2) Dim sn As String ↑これを「Dim MyArray As Variant」の下にでも追加して sn = .Name ↑これを「MyArray = Range(.Cells(r, 1), .Cells(MaxRow, MaxCol))」の下に追加。 ↓このくだりをこんな感じに書き換える。 If .Cells(1, 1) = "" Then '最初だけ1行目から貼り付け With Range(.Cells(1, 1), .Cells(UBound(MyArray), MaxCol)) .Offset(, 1).Value = MyArray .Columns(1).Value = sn .Cells(1, 1).Value = "シート名" End With Else '最初以外は最終行の次に貼り付け With Range(.Cells(MaxRow + 1, 1), .Cells(MaxRow + UBound(MyArray), MaxCol)) .Offset(, 1).Value = MyArray .Columns(1).Value = sn End With End If (3) ' Sheets(Array("一山", "二階堂", "三田", "四方")).Select ' Sheets("四方").Activate ↓こっちに変更 Dim i As Long Sheets(2).Select For i = 3 To Sheets.Count Sheets(i).Select False Next ホントはもうちょっと作り込まないと、安定した動作の確保までは至らないと思いますが、 まぁ、 > 私はマクロはほとんどわかりません。 と申告なさってる方に、 このタイミングでわざわざ申し上げるのもアレですかね。 ^^; (白茶) 2023/06/20(火) 18:41:32 ---- >私はマクロはほとんどわかりません。 とはいえ、マクロを改造しようとおもうならば、まずは理解するところから手を付けることを強く推奨します。 そのうえで気になる点など。 ■1 >シートを読み込む際に各ファイルの一番左のシートのみを読み込みたいです ブックの1番目のシートが【一番左】のシートになりますから、それを取得すればよいと思います。 すなわち↓で取得できます。 ワークブックオブジェクト.Worksheets(1) ■2 >A列にシート名(=営業担当者名)を入れたいです シート名は↓で取得できます。 シートオブジェクト.Name ■3 >一番左の統合シート以外のシートをすべて削除にしたいです 発想を変えて、最後のシート〜2番目のシートまでを【順番に】削除すればよいとおもいます。 なお、最後のシートが何番目かは、↓のようにブックの枚数を数えるとわかります ワークブックオブジェクト.Worksheets.Count 以下、現状のコードを拝見しての感想です。 ■4 >個々の営業のファイルとデータ統合用のファイルは一つのフォルダに入れています。 ですから、カレントディレクトリを調べずとも【データ統合用のファイル】のPathを調べればフォルダは特定可能です。 踏まえて、↓はちゃんとフォルダを指定すべきです。 Filename = Dir("*.xlsx") ■5 「■1」と被りますが↓だと全シートをコピー(して挿入)という命令になっていますから、1番目のシートのみ指定すべきです。 Worksheets.Copy after:=ThisWorkbook.Worksheets(ShCount) ■6 ↓のコメントは適切ではありません s = 1 '最大行を超えた場合次の統合シートを作成するための番号 踏まえて s = 1 Worksheets.Add Before:=Worksheets(s) '新規に統合シートを追加 ActiveSheet.Name = "統合" Set JoinSh = ActiveSheet '統合シートを変数に格納 For i = s + 1 To Worksheets.Count ↑は↓とおなじです。 Worksheets.Add(Before:=Worksheets(1)).Name = "統合" Set JoinSh = Worksheets("統合") For i = 2 To Worksheets.Count ■7 「■6」に関連して With JoinSh '統合シート ↑は↓とおなじです。 With Worksheets("統合") ■8 否定はしませんが MyArray = Range(.Cells(r, 1), .Cells(MaxRow, MaxCol)) Range(.Cells(1, 1), .Cells(UBound(MyArray), MaxCol)) = MyArray ↑は↓とほぼ同じです。 Range(.Cells(r, 1), .Cells(MaxRow, MaxCol)).Copy .Cells(1, 1).【値貼り付けをする命令】 (もこな2) 2023/06/20(火) 19:07:14 ---- 参照元の記事のコードが間違っていますね。 (1) With JoinSh End With の中で、JoinShを変更している点。 (2) For i = s + 1 To Worksheets.Count Next の中で統合シートの追加によって、元のindexではすべてのシートを対象にできていない点 の二つです。 従って、今使っているコードも、 一つの統合シートでは行溢れが発生する場合には、正常に転記がされません。 時間が取れれば、修正案を書いてみたいと思いますが、他の方から提案があれば幸いでもあります。 (xyz) 2023/06/20(火) 19:17:09 ---- コードは見てません。 ただ参照元のサイトの画像のように同じ様式の表を1枚のシートにまとめるだけでしたら、パワークエリをお勧めします。 参考サイト(power query 複数シート 結合 と検索すればいくらでも出てくると思います。) https://tech-blog.cloud-config.jp/2022-07-14-power-query-excel-sheet-merge https://hamachan.info/excel2019-powerquery-ketugou/ https://daitaideit.com/excel-powerquery-join-multi-sheet/ (フォーキー) 2023/06/20(火) 20:11:12 ---- パワークエリ案もあるところですが追加で何点か。 ■9 そもそも【1つのシート】にデータを集約したいなら、ワークシートのコピー挿入は不要だと思います。 そのほか指摘していない部分も含めて、冗長と思える部分があるように思いますので、繰り返しになりますがどのような処理を行うコードになっているのか自己検証するとともに、必要な処理の流れを一旦整理されることをお勧めします。 ■10 暇つぶしに私ならどのように処理するかと考えてみました。少々トリッキーになりましたが一例として提示します。 ※ 完成品のプレゼントを意図したものでなく研究用として提示しています。 ※ 採用される場合はステップ実行等により研究の上、必要な部分のみご自身のコードに組み込んでください。 Sub 研究用() Dim dstRNG As Range, srcRNG As Range Dim フラグ As Long Dim Filename As String Dim i As Long Stop 'ブレークポイントの代わり Set dstRNG = Workbooks.Add(Template:=xlWBATWorksheet).Worksheets(1).Range("C1") dstRNG.Parent.Name = "統合" Filename = Dir(ThisWorkbook.Path & "¥*.xlsx") Do While Filename <> "" If Filename <> ThisWorkbook.Name Then '自ブックは"xlsm"だから実際には要らない With 【ブックを開く命令】(ThisWorkbook.Path & "¥" & Filename).Worksheets(1) Set srcRNG = .Range("A1", .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(1, .Columns.Count).End(xlToLeft).Column)) Set srcRNG = srcRNG.Resize(srcRNG.Rows.Count - フラグ).Offset(フラグ) srcRNG.Copy On Error GoTo 行あふれ処理 dstRNG.【値貼付けする命令】 Application.CutCopyMode = False dstRNG.Offset(, -2).Resize(srcRNG.Rows.Count).Value = Filename dstRNG.Offset(, -1).Resize(srcRNG.Rows.Count).Value = "「■2」参照" フラグ = 1 Set dstRNG = dstRNG.Offset(srcRNG.Rows.Count) On Error GoTo 0 .Parent.【ブックを保存せず閉じる命令】 End With End If Filename = Dir() Loop For i = 1 To dstRNG.Parent.Parent.Worksheets.Count Step 1 dstRNG.Parent.Parent.Worksheets(i).Range("A1:B1").Value = Array("由来ブック", "由来シート") Next i Exit Sub 行あふれ処理: Stop 'ブレークポイントの代わり Err.Clear Set srcRNG = srcRNG.Offset(-1).Resize(srcRNG.Rows.Count + 1) Set dstRNG = Worksheets.Add(after:=dstRNG.Parent).Range("C1") dstRNG.Parent.Name = "統合" & dstRNG.Parent.Parent.Worksheets.Count Resume End Sub (もこな2) 2023/06/20(火) 22:55:47 ---- ふと我に返ったら、統合シートが行あふれする(つまり100万行を超える)ことなど 質問者さんのシチュエーションではありそうにもないと思えるので、 要望のあった3点だけ対応して、今のまま使い続けたらどうでしょう。 修正したコードを書いて見ましたが、それはそれで今のものと違うので、 質問者さんも混乱するでしょう。余り益がある気もしませんので、提示しません。 また、他の方から別提案もされていますので、そちらを参照してください。 ============ ということで、以下は余談ということで、興味があるかただけお読みください。 (1) | With JoinSh | End With | の中で、JoinShを変更している点。 言葉足らずでした。 JoinShを変更すると、直ちにそれがWithステートメントのドット構文に反映されると 思っているようだ、という点です。 簡単な例で言うと、こんな感じです。 Sub test() Dim r As Range Set r = [A1:B3] With r Debug.Print .Address Set r = [C1:D3] Debug.Print .Address '$C$1:$D$3ではなく、元のままの$A$1:$B$3が出力されます。 End With End Sub 元記事の例で言えば、 "統合2"シートを作って、JoinShにそれをバインドさせた後に .(ドット)で参照されるのは、 "統合2"シートではなく、元の"統合"シートです。そこに書き込んでしまっているわけです。 (2) 二点目は、統合シートを左から追加しているので、 For i = s + 1 To Worksheets.Count で操作される対象シートが、そのシート挿入で狂ってくることを想定していない、という点です。 これは、統合シートを右端に増やしていけばいいだけの話でしょう。 どうしても最初に統合シートを置きたい、ということなら、 上記で作業終了後に、尻尾のシートから順に、 "統合"を含むシートの場合に、 シートの最初に移動させる処理を加えればよいでしょう。 ネット上に上がっているコードも、行溢れへの対応とうたっておきながら、 結構怪しいものもあるんだなあ、と思いました。 まあ、ミスは誰もしますのでね。使用に際してはよく確認することが必要です。 (xyz) 2023/06/21(水) 08:55:43 ---- たくさんのコメントありがとうございました (白茶)さんにいただいた3点を変更して希望するものになりました データ統合部分の If InStr(Sh.Name, "統合") <> 0 Then Sh.Delete 'すでに統合シートが存在する場合は一旦削除 は私の最初の前回データの削除部分で "統合"シートはDeleteだけしてシート自体は残しておいたものを削除していたのでカットしました。 他、s = 1 '最大行を超えた場合のくだりは皆さんがおっしゃる通り 100万行を超える想定はないので適当に削除してみたところ動かなくなってしまったので そのまま使うことにします。 (フォーキー)さんのpower query なるもの初めて知りました。 自分でもマクロを理解しないまま人様の書いてもらったコードを利用するのはあまりよくないことはわかっています。 私のレベルであればpower queryを使いこなせるようになった方がいい気がするので こちらも並行して活用してみようと思います。 1点追加で質問です。 現状のデータの統合マクロで各シートのデータの入っている終わりの行はどこで判断しているのでしょうか。 よくあるマクロではA列にデータの入っている終わりの行を使っていることが多いので A列は途中で空白にしてはいけないのかと思っていましたが、試しに間のA列を空白にしてみましたが 空白の列もそれ以降のデータの終わりの行までちゃんと統合されていました。 但し、終わりの行から3行ほど全くの空白行を入れてそのあとD列F列あたりに文字を入れてみましたがその行は統合されていませんでした。 次は営業さん各自のエクセルの入力制御やルールを考えなければならないと思い質問です。 よろしくお願いいたします。 (マクロって難しい) 2023/06/21(水) 18:13:57 ---- | MaxRow = .Cells(Rows.Count, 1).End(xlUp).Row '1列目で最終行を取得 | MaxCol = .Cells(1, Columns.Count).End(xlToLeft).Column '1行目で最終列を取得 | MyArray = Range(.Cells(r, 1), .Cells(MaxRow, MaxCol)) ここのことでしょう。 Rows.Count は、ワークシートの行数です。1,048,576です。 つまり、Cells(Rows.Count, 1)はA列の最終行のセルです。 そこから、Ctrl + ↑ でジャンプした行の行番号を、 「データのある最終行」と判定しています。 列についても同じ考え方です。1行目の最終列から左にジャンプした列番号を取得しています。 MyArray = Range(.Cells(r, 1), .Cells(MaxRow, MaxCol)) でその範囲のデータを配列に取り込んで、 それを統合シートに転記しています。 (xyz) 2023/06/21(水) 20:34:38 ---- >現状のデータの統合マクロで各シートのデータの入っている終わりの行はどこで判断しているのでしょうか。 >よくあるマクロではA列にデータの入っている終わりの行を使っていることが多いので >A列は途中で空白にしてはいけないのかと思っていましたが、試しに間のA列を空白にしてみましたが >空白の列もそれ以降のデータの終わりの行までちゃんと統合されていました。 既に適切なアドバイスがありますが、「VBA 最終行」というキーワードなどで検索すると、画像付きで解説しているサイトがありますからより理解しやすいと思います。 【参考】 https://excel-ubara.com/excelvba4/EXCEL222.html https://www.tipsfound.com/vba/09002-vba (もこな2) 2023/06/22(木) 07:54:50 ---- (xyz)さん(もこな2)さん 上からではなく下から最終行を見つけているのですね。 だから終わりの行から3行ほど全くの空白行を入れて そのあとD列F列あたりにいれた文字は統合されなかった。 ものすごくわかりやすくて納得しました ありがとうございます!! (マクロって難しい) 2023/06/22(木) 11:31:56 ---- >そのあとD列F列あたりにいれた文字は統合されなかった。 そういう場合も含めた包括的な対応策が、 もこな2さんから紹介された下記記事に記載されています。 https://excel-ubara.com/excelvba4/EXCEL222.html 是非。 (xyz) 2023/06/22(木) 11:50:41 ---- (xyz)さん 参考記事も読みました。 >そのあとD列F列あたりにいれた文字 この場合も統合されてほしいのですが 参考記事を読んで私なりの解釈としては ・CurrentRegion 途中に空白行(何も入っていない行)がある場合は、そこまでの行になってしまうので却下 ・SpecialCells(xlCellTypeLastCell) ・UsedRange 罫線や行高の変更まで範囲に含めてしまうのでこれも却下 ・Findメソッド エクセルの検索機能を使っていることはわかりましたが 注意点の指定オプションがシート操作とリンクしている点とか 全体的に今の私には難しく理解及ばす で、回避策として 営業の管理表側でA列を操作できないようにロックしておき A列にはB列以降に何か一つでもデータの入ったセルがある場合シート名(営業担当氏名)を取得するようにしました。 これなら統合のマクロでA列にシート名(=営業担当者名)を入れたいとしていたのをなしにして。 =IF(COUNTA(B2:AW2)>0,RIGHT(CELL("filename",$A$1),LEN(CELL("filename",$A$1))-FIND("]",CELL("filename",$A$1))),"") 自分のできる範囲で試行錯誤って感じですが。。。 (マクロって難しい) 2023/06/22(木) 14:48:24 ---- 最終行 = Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row 最終列 = Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column これは説明が要りますね。 【ながーい説明】 (1)After引数が省略されています。 このときは、検索対象範囲の左上端のセル(つまり、A1セル)を起点に、 その次のセルから検索を始めます。 (2)SearchDirection:=xlPrevious ですから、後ろ向きに進みます。 "A1セル"の一つ前のセルとはどこでしょうか。 これは"メビウスの帯"のように(知らなければスキップ下さい)、 "A1セル"の一つ前のセルは、(1,048,576,"XFD")セルと考えます。 (3)SearchOrder:=xlByRows ですから、行毎に検索していきます。 つまり、 (1,048,576,"XFD")セル → (1,048,576,"XFC")セル → ・・・・ → (1,048,576,"A") → (1,048,575,"XFD")セル → (1,048,575,"XFC")セル → ・・・・ → (1,048,575,"A") → ・・・・ ( 1,"XFD")セル → ( 1,"XFC")セル → ・・・・ → ( 1,"A") の順序に、"*"、つまり、""以外の何かが入っているセルを検索します。 この結果、(罫線とか色とかは無視して)何かが入っている一番下の行が最初にヒットします。 (4)そのRowですから、結局、最終行を得ることができるわけです。 (5)最終列も同様に、シートの右下隅のセルから、列に沿って、後ろ向きに検索しますから、 ""以外の何かが入った最終列を求めることができるわけです。 これは、それぞれが一行で書けるので、理屈が分かってしまえば、使いまわしができます。 # こちらの掲示板でもこれを使って何回か回答したことがあります。 【結論】 | MaxRow = .Cells(Rows.Count, 1).End(xlUp).Row '1列目で最終行を取得 | MaxCol = .Cells(1, Columns.Count).End(xlToLeft).Column '1行目で最終列を取得 をそれぞれ、 MaxRow = .Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row MaxCol = .Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column とすればよいはずです。 (xyz) 2023/06/22(木) 16:36:49 ---- Cellsの代わりに .UsedRangeとしてもよいと思います。(速度にさほどの差はないと思いますが) MaxRow = .UsedRange.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row MaxCol = .UsedRange.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column また、 > また、Findメソッドは指定オプションがシート操作とリンクしている点については注意してください。 これはマクロで逆向きの検索をすることで、それが次回に検索する際に記憶されていて、 そのオプションが使用されることを懸念したものと思いますが、 それを回避するには、マクロの最後に以下の2行を追加すればよいでしょう。 これで、そうした懸念は払拭されるはずです。 Dim dummy As Range Set dummy = Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlNext) (xyz) 2023/06/22(木) 17:11:02 ---- (xyz)さん .Cells.でも .UsedRange.でも希望する結果が得られました。 "A1セル"の一つ前のセルは1,048,576,"XFD"セルで後ろ向きに検索していく。 本当ものすごくわかりやすい説明でとても勉強になりました。 ありがとうございました。 (マクロって難しい) 2023/06/23(金) 09:36:14 ...
https://www.excel.studio-kazu.jp/wiki/kazuwiki/202306/20230620143850.txt - [detail] - similar
PREV NEXT
Powered by Hyper Estraier 1.4.13, with 97054 documents and 608269 words.

訪問者:カウンタValid HTML 4.01 Transitional