質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

1988閲覧

XML一括出力 なぜでない

sigret

総合スコア45

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2018/03/27 07:34

以下のマクロで複数シートをXMLファイルに出力したいのですが、出力こそ出来るものの、中身が空っぽのまま出力されてしまいます。
またDo While i < 13をDo While i < 5、とループさせずに一つのファイルだけ出力させるとこっちは中身がちゃんと入ったまま出力されます。
なぜ複数同時にやると空になるのでしょう・・。
また複数同時に出力する方法はあるのでしょうか?
よろしくお願いします。

Option Explicit Sub XML() Dim TargetWorkbook As Workbook Dim OpenFileName As String Dim x As String Dim y As String Dim i As Integer Dim Row As Integer Dim Col As Integer Dim SheetName As String Dim xmlObj As MSXML2.IXMLDOMNode Dim xmlObj1 As MSXML2.IXMLDOMNode Dim xmlObj2 As MSXML2.IXMLDOMNode Dim xmlObj3 As MSXML2.IXMLDOMNode Dim xmlObj4 As MSXML2.IXMLDOMNode Dim xmlDoc As MSXML2.DOMDocument60 Dim xmlPI As IXMLDOMProcessingInstruction Dim FileName As String Dim xmlReader As New SAXXMLReader Dim xmlWriter As New MXXMLWriter i = 4 OpenFileName = Application.GetOpenFilename("Microsoft Excelブック,*.xls?") Do While i < 13 Set TargetWorkbook = Workbooks.Open(OpenFileName) If OpenFileName <> "False" Then Set xmlDoc = New MSXML2.DOMDocument60 Set xmlPI = xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8""")) Row = 3 Col = 2 SheetName = TargetWorkbook.Worksheets(i).Name Do While Col < 7 If TargetWorkbook.Worksheets(i).Cells(Row, Col).Value <> "" Then If Col = 2 Then x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value Set xmlObj = xmlDoc.appendChild(xmlDoc.createNode(NODE_ELEMENT, x, "")) xmlObj.Text = y ElseIf Col = 3 Then x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value Set xmlObj1 = xmlObj.appendChild(xmlDoc.createNode(NODE_ELEMENT, x, "")) xmlObj1.Text = y ElseIf Col = 4 Then x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value Set xmlObj2 = xmlObj1.appendChild(xmlDoc.createNode(NODE_ELEMENT, x, "")) xmlObj2.Text = y ElseIf Col = 5 Then x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value Set xmlObj3 = xmlObj2.appendChild(xmlDoc.createNode(NODE_ELEMENT, x, "")) xmlObj3.Text = y ElseIf Col = 6 Then x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value Set xmlObj4 = xmlObj3.appendChild(xmlDoc.createNode(NODE_ELEMENT, x, "")) xmlObj4.Text = y End If Col = 2 Row = Row + 1 Else: Col = Col + 1 End If Loop If TargetWorkbook.Worksheets(i).Name = "a" Then FileName = "a.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "b" Then FileName = "b.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "c" Then FileName = "c.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "d Then FileName = "d.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "e" Then FileName = "e.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "f" Then FileName = "f.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "g" Then FileName = "g.xml" ElseIf TargetWorkbook.Worksheets(i).Name = "h" Then FileName = "h.xml" End If xmlWriter.indent = True Set xmlReader.contentHandler = xmlWriter xmlReader.Parse xmlDoc.XML xmlDoc.loadXml xmlWriter.output xmlDoc.Save (FileName) End If i = i + 1 Loop End Sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

まずコードの書き方から、
・TargetWorkbook.Worksheets(i) → Withを使って省略しましょう
・If TargetWorkbook.Worksheets(i).Name = "a" Then ・・・ → Select Case を使いましょう
※SheetNameを使わない理由はあるのでしょうか?

正しい処理は分かりませんが、状況から
「xmlDoc.Save (FileName)」の後に、Close や Nothing 処理は不要なのでしょうか?

また、「FileName = "h.xml"」等としてますが、
パスを指定しない場合は確かマイドキュメントへ自動的に保存されますが、
分かりにくいので、ThisWorkBook.Path & "" & FileName 等でちゃんとパスを指定すべき。

投稿2018/03/27 08:46

ExcelVBAer

総合スコア1175

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sigret

2018/03/27 13:06

ExcelVBAさん 回答ありがとうございます。 コードの書き方については完成ののち(とりあえず出力できることが確認できてから)対応したいと思います。 Close や Nothing の処理なのですがCloseはClose処理をすると(.Closeを追記)エラーが出てしまいます・・。 Nothing 至っては何をNothing にすればいいのかわからず・・取り合えず思いつくままに(xmlDoc、FileName など)片っ端からNothing で構文を入れてみたのですがやはり中身が空で出力されます・・。 先輩曰く何か初期化ができていない?そうなのですが自分としては変数は全て初期化できている(つもり)です・・。
ExcelVBAer

2018/03/28 00:35

プロの料理人が料理している間にキッチンがグチャグチャになるでしょうか? コードを簡潔にすることを後回しにする人が、いい仕事できるんでしょうか? 個人的には一時的な書き方をした場合でも動くようになったら即修正と決めています。 なぜなら、後回しにしていくと面倒になってそのままにしがちだからです。 そうすると、テストフェーズでバグが見つかった時に、 コードが読み難く、修正に手間がかかります。 そして往々にして、適当に作った箇所でバグが見つかる事を、 何回も経験して分かってます。 なので、原因追及が困難な今だからこそ、 息抜きついでに合間にできることは先にやっておく方がいいと思います。 ※改善点の追加です 単純にシートを回しているのであれば、Do~Loop ではなく、For~Next の方が適しています。 コードは正確に、簡潔に。 これを常日頃から実践していくと、 不要なバグに悩まされる事が少なくなりますよ。学生さん。
sigret

2018/03/28 00:46

なるほど・・。自分が元調理師だったのでその喩はすごく良く分かります。 汚く散らかしていたらブチ切れものでしたし(笑) 何においてもそうなんですね。精進します!
ExcelVBAer

2018/03/28 01:24

おぉ、まさかの回答でビックリ!! 他の業界でも通じるところがあるもんですね~(笑) とあるイベントでプロ調理師のお手伝いをする機会があり、 片付ける事の重要さを教えてもらった事が役に立ったみたいです. 折角なので、参考コードを少し(※インデントは調整してください) Dim TargetSheet As WorkSheet Set TargetSheet = TargetWorkbook.Worksheets(i) With TargetSheet Select Case .Name Case "a" : FileName = "a.xml" End Select End With
guest

0

結論

xmlWriterなどをループ毎に初期化する。

デバッグの過程

xmlDoc.xmlをウォッチ式で追ったところ、xmlDoc.LoadXML xmlWriter.outputで空文字列となりました。

xmlWriter.outputを確認したところ、ループ毎に<?xml version="1.0" encoding="UTF-16" standalone="no"?>が増えており、2回目以降は適当なXMLではなくなったのが、空出力の原因だと思われます。

その他粗探し

ExcelVBAer さんも指摘されていますが、ちょっと読みにくいコードです。

読みにくいとバグが混入しやすいだけでなく、回答側の精神的ハードルも上がるため、回答が少なくなる、遅くなる可能性があります
(私も昨日の時点で質問に気付いていましたが、コードの整理が面倒だったため後回しにしました)。


以下の処理はループの外に出しましょう。
また、If文は前に持ってこないと意味がありません。
Ifの判定の結果、"False"であれば即座にExit Subすると、以降のネストを一段減らせます。

vba

1Set TargetWorkbook = Workbooks.Open(OpenFileName) 2 If OpenFileName <> "False" Then

中央、列番号のIf文内の以下の処理が重複していますので、Ifの外に出した方が見やすくなります。

vba

1x = TargetWorkbook.Worksheets(i).Cells(Row, 7).Value 2y = TargetWorkbook.Worksheets(i).Cells(Row, 9).Value

投稿2018/03/28 13:31

編集2018/03/28 13:32
imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

試せる環境にいないので推測ですが、createElementしていないのにノードだけ追加されているのでxmlとしての構造が整わず、空出力となる?
MSXML2におけるノードとエレメントの考えは調べれば出てくると思います

投稿2018/03/27 16:40

Satou0317

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sigret

2018/03/27 23:52

Satou0317さん 回答ありがとうございます。 しかし一枚目(複数出力時の最初の一回)はちゃんと出力されることから構造自体は間違ってはないのでは、と考えられます・・。 createElementに関してももう一度調べなおしてみます。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問