Есть ли способ заставить Excel сохранить атрибуты XML в корневом элементе? - PullRequest
7 голосов
/ 29 июня 2009

Я экспериментировал с использованием MS Excel 2007 для редактирования табличных данных, хранящихся в файле XML. Он хорошо выполняет импорт и даже проверку данных XML по схеме (файл xsd), но при экспорте он удаляет атрибуты xmlns, xlmns: xsi и xsi: schemaLocation из корневого элемента. Это также изменяет пространство имен по умолчанию на явное пространство имен.

Вот сравнение до / после:

До (файл XML перед импортом в Excel)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<database
  xmlns="experimentManager"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="experimentManager Database.xsd">
  <conditionTokens>
    ...
  </conditionTokens>
  <participants>
    ...
  </participants>
</database>

После (файл XML после экспорта из Excel)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:database xmlns:ns1="experimentManager">
    <ns1:conditionTokens>
        ...
    </ns1:conditionTokens>
    <ns1:participants>
        ...
    </ns1:participants>
</ns1:database>

Есть ли какой-нибудь способ предотвратить исключение Excel этих атрибутов и создание беспорядка в пространствах имен? Я прочитал справку MS по отображению XML и импорту / экспорту, но в графическом интерфейсе, похоже, нет никаких настроек для того, что я хочу сделать. Если мне нужно написать собственный макрос, это возможно, но я бы не стал этого делать, если есть лучший / более простой способ.

Второй вопрос: существует ли лучший инструмент, позволяющий легко редактировать определенные части файлов XML с помощью пользовательского интерфейса в стиле Excel?

Ответы [ 3 ]

4 голосов
/ 30 июня 2009

Хорошо, я прикусила пулю и написала хороший старый макрос VBA. Я подумал, что поделюсь этим со всеми вами на случай, если кто-то столкнется с той же проблемой.

Этот макрос в основном вызывает встроенный в Excel метод XML Export (), а затем выполняет серию замен текста в результирующем файле. Замена текста полностью на ваше усмотрение. Просто поместите их в таблицу, как показано в ссылке ниже ...

Пример того, как настроить «правила замены»: Нажмите меня, чтобы открыть экран

В этом примере я заменил табуляцию пробелом, ": ns1" пустым, "ns1:" пустым, а урезанный корневой элемент оригинальным корневым элементом.

Вы можете отформатировать правила замены любым удобным вам способом, если вы будете следовать этим инструкциям:

  1. Выберите все ячейки "найти что" и дайте им имя * "FindWhat" (не включайте строку заголовка в ваш выбор; пробелы будут игнорироваться).
  2. Выберите все ячейки «заменить на» и дайте им имя * «Заменить на» (между ячейками «найти что» и «заменить на» должно быть взаимно-однозначное соответствие; используйте пробелы для удаления нежелательного текста) ).
  3. Введите имя карты XML где-нибудь в своей рабочей книге и назовите эту ячейку "XmlMap".
  4. Запустить макрос. (Вам будет предложено указать файл, в который вы хотите экспортировать.)

* Если вы не знакомы с диапазонами именования в Excel 2007, перейдите на вкладку Формулы и выберите «Диспетчер имен».

Хорошо, я больше не буду держать вас в напряжении (LOL) ... вот код для макроса. Просто поместите его в модуль в редакторе VBA. С этим бесплатным кодом я не даю никаких гарантий (его можно легко сломать, если вы не назовете диапазоны должным образом), но пара примеров, которые я пробовал, сработали для меня.

Option Explicit

Sub ExportXml()
    Dim exportResult As XlXmlExportResult
    Dim exportPath As String
    Dim xmlMap As String
    Dim fileContents As String
    exportPath = RequestExportPath()
    If exportPath = "" Or exportPath = "False" Then Exit Sub
    xmlMap = range("XmlMap")
    exportResult = ActiveWorkbook.XmlMaps(xmlMap).Export(exportPath, True)
    If exportResult = xlXmlExportValidationFailed Then
        Beep
        Exit Sub
    End If
    fileContents = ReadInTextFile(exportPath)
    fileContents = ApplyReplaceRules(fileContents)
    WriteTextToFile exportPath, fileContents
End Sub

Function ApplyReplaceRules(fileContents As String) As String
    Dim replaceWorksheet As Worksheet
    Dim findWhatRange As range
    Dim replaceWithRange As range
    Dim findWhat As String
    Dim replaceWith As String
    Dim cell As Integer
    Set findWhatRange = range("FindWhat")
    Set replaceWithRange = range("ReplaceWith")
    For cell = 1 To findWhatRange.Cells.Count
        findWhat = findWhatRange.Cells(cell)
        If findWhat <> "" Then
            replaceWith = replaceWithRange.Cells(cell)
            fileContents = Replace(fileContents, findWhat, replaceWith)
        End If
    Next cell
    ApplyReplaceRules = fileContents
End Function

Function RequestExportPath() As String
    Dim messageBoxResult As VbMsgBoxResult
    Dim exportPath As String
    Dim message As String
    message = "The file already exists. Do you want to replace it?"
    Do While True
        exportPath = Application.GetSaveAsFilename("", "XML Files (*.xml),*.xml")
        If exportPath = "False" Then Exit Do
        If Not FileExists(exportPath) Then Exit Do
        messageBoxResult = MsgBox(message, vbYesNo, "File Exists")
        If messageBoxResult = vbYes Then Exit Do
    Loop
    RequestExportPath = exportPath
End Function

Function FileExists(path As String) As Boolean
    Dim fileSystemObject
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    FileExists = fileSystemObject.FileExists(path)
End Function

Function ReadInTextFile(path As String) As String
    Dim fileSystemObject
    Dim textStream
    Dim fileContents As String
    Dim line As String
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    Set textStream = fileSystemObject.OpenTextFile(path)
    fileContents = textStream.ReadAll
    textStream.Close
    ReadInTextFile = fileContents
End Function

Sub WriteTextToFile(path As String, fileContents As String)
    Dim fileSystemObject
    Dim textStream
    Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
    Set textStream = fileSystemObject.CreateTextFile(path, True)
    textStream.Write fileContents
    textStream.Close
End Sub
0 голосов
/ 10 апреля 2019

Я попытался принять принятый ответ, и, как и человек, представленный ниже, я получил глобальную ошибку Range, так как Excel очень сложно узнать диапазон XML-файла. Тем не менее, я создал альтернативный метод для этого, что мне не хотелось бы делать, но, к сожалению, банковская система не может принять XML-файл с ns1: в нем.

Если вы просто хотите, чтобы что-то было удалено, используйте следующую команду, чтобы сохранить файл как текстовый файл, затем снова откройте его в Excel, удалите ns1: и сохраните его как .prn. Вам нужно только изменить prn на xml.

Workbooks.OpenText Filename:= _
    Store & "\" & "\" & sFilename & ".txt", _
    Origin:=xlMSDOS, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
    xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
    Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(1, 1), _
    TrailingMinusNumbers:=True
Cells.Replace What:="ns1:", Replacement:="", LookAt:=xlPart, SearchOrder _
    :=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
ActiveWorkbook.SaveAs Filename:= _
    Store & "\" & "\" & sFilename & ".prn", _
    FileFormat:=xlTextPrinter, CreateBackup:=False
ActiveWorkbook.Close savechanges:=False
0 голосов
/ 09 марта 2015

На самом деле, это намного проще, чем это.

  1. Измените суффикс .xlsx на .zip - формат xlsx фактически заархивирован xml файлами!
  2. Открыть файл zip в проводнике Windows
  3. Перейдите в подкаталог xl
  4. Скопируйте файл xmlMaps.xml в папку вне папки .zip
  5. Отредактируйте файл, чтобы заменить записи nsX: предпочитаемым пространством имен, и сохраните изменения.
  6. Скопируйте файл и перезапишите версию в папке .zip
  7. Переименуйте папку обратно в .xslx

Теперь на ваших картах XML будут отображаться предпочитаемые вами пространства имен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...