Puedo exportar datos de Microsoft Excel mediante Macros de Excel(VBScript).
Como el archivo es lua, me exportación como UTF-8.
La única manera en que puedo hacer UTF-8 en Excel es usando adodb.stream como este

set fileLua = CreateObject("adodb.stream")
fileLua.Type = 2
fileLua.Mode = 3
fileLua.Charset = "UTF-8"
fileLua.Open
fileLua.WriteText("test")
fileLua.SaveToFile("Test.lua")
fileLua.flush
fileLua.Close

Quiero hacer eliminar la lista de materiales de Prueba.lua pero no sé cómo.
(Porque La Prueba.lua tiene algunas de texto unicode, tengo que usar el formato UTF-8.)

¿Sabes cómo hacer archivo UTF-8 sin BOM en el archivo de excel?
Gracias de antemano.

InformationsquelleAutor P-P | 2010-11-10

6 Comentarios

  1. 34

    También tengo el mismo problema: tiene que exportar datos de Excel (Office 2003, VBA6.5) a UTF-8 archivo codificado. Encontró la respuesta de tu pregunta ! Debajo de mi ejemplo, donde yo también tira de la lista de materiales mediante truco #2 de boost (¡gracias!) respuesta. No me llega el #1 de trabajar y nunca trató de #3.

    Sub WriteUTF8WithoutBOM()
        Dim UTFStream As Object
        Set UTFStream = CreateObject("adodb.stream")
        UTFStream.Type = adTypeText
        UTFStream.Mode = adModeReadWrite
        UTFStream.Charset = "UTF-8"
        UTFStream.LineSeparator = adLF
        UTFStream.Open
        UTFStream.WriteText "This is an unicode/UTF-8 test.", adWriteLine
        UTFStream.WriteText "First set of special characters: öäåñüûú€", adWriteLine
        UTFStream.WriteText "Second set of special characters: qwertzuiopõúasdfghjkléáûyxcvbnm\|Ä€Í÷×äðÐ[]í³£;?¤>#&@{}<;>*~¡^¢°²`ÿ´½¨¸0", adWriteLine
    
        UTFStream.Position = 3 'skip BOM
    
        Dim BinaryStream As Object
        Set BinaryStream = CreateObject("adodb.stream")
        BinaryStream.Type = adTypeBinary
        BinaryStream.Mode = adModeReadWrite
        BinaryStream.Open
    
        'Strips BOM (first 3 bytes)
        UTFStream.CopyTo BinaryStream
    
        'UTFStream.SaveToFile "d:\adodb-stream1.txt", adSaveCreateOverWrite
        UTFStream.Flush
        UTFStream.Close
    
        BinaryStream.SaveToFile "d:\adodb-stream2.txt", adSaveCreateOverWrite
        BinaryStream.Flush
        BinaryStream.Close
    End Sub

    La ADO Objeto de Secuencia de referencia he utilizado.

    • este es un buen uno, muchas gracias
  2. 9

    Si alguien más está luchando con la adTypeText constante, es necesario incluir «Microsoft ActiveX Data Objects 2.5 Biblioteca de Objeto» en el menú Herramientas->Referencias.

    • O reemplazarlo con el número 2 (sin las comillas). Esto no es ni siquiera necesario, porque aunque adTypeText es el valor predeterminado de todos modos.
    • constante adTypeBinary = 1. (fuente:w3schools )
  3. 7

    Un par de posibilidades:

    1. Poner el texto en el buffer como UTF-8, Tipo=2, pero, a continuación, establecer el Tipo=1 (binario) y de escritura que fuera. Que podrían convencer a ADODB.Secuencia para saltar la adición de la lista de materiales.

    2. Crear otro buffer, como de tipo binario, y utilizar el método CopyTo para copiar los datos a que búfer desde un punto después de la lista de materiales.

    3. Leer el archivo de nuevo el uso de secuencias de comandos.FileSystemObject, recorte la lista de materiales, escribir de nuevo

  4. 1

    Editar

    Un comentario de rellampec me alertó sobre una mejor abandonar el LF había descubierto, se añadió al final del archivo por user272735 del método. He añadido una nueva versión de mi rutina al final.

    Post Original

    Yo había estado usando user272735 del método con éxito durante un año cuando descubrí que añade un LF al final del archivo. No me di cuenta de este extra LF hasta que se me hizo muy detallada pruebas, de manera que este no es un importante error. Sin embargo, mi última versión descarta que LF sólo en caso de que alguna vez llegó a ser importante.

    Public Sub PutTextFileUtf8(ByVal PathFileName As String, ByVal FileBody As String)
    
      ' Outputs FileBody as a text file (UTF-8 encoding without leading BOM)
      ' named PathFileName
    
      ' Needs reference to "Microsoft ActiveX Data Objects n.n Library"
      ' Addition to original code says version 2.5. Tested with version 6.1.
    
      '  1Nov16  Copied from http://stackoverflow.com/a/4461250/973283
      '          but replaced literals with parameters.
      ' 15Aug17  Discovered routine was adding an LF to the end of the file.
      '          Added code to discard that LF.
    
      ' References: http://stackoverflow.com/a/4461250/973283
      '             https://www.w3schools.com/asp/ado_ref_stream.asp
    
      Dim BinaryStream As Object
      Dim UTFStream As Object
    
      Set UTFStream = CreateObject("adodb.stream")
    
      UTFStream.Type = adTypeText
      UTFStream.Mode = adModeReadWrite
      UTFStream.Charset = "UTF-8"
      ' The LineSeparator will be added to the end of FileBody. It is possible
      ' to select a different value for LineSeparator but I can find nothing to
      ' suggest it is possible to not add anything to the end of FileBody
      UTFStream.LineSeparator = adLF
      UTFStream.Open
      UTFStream.WriteText FileBody, adWriteLine
    
      UTFStream.Position = 3 'skip BOM
    
      Set BinaryStream = CreateObject("adodb.stream")
      BinaryStream.Type = adTypeBinary
      BinaryStream.Mode = adModeReadWrite
      BinaryStream.Open
    
      UTFStream.CopyTo BinaryStream
    
      ' Oriinally I planned to use "CopyTo Dest, NumChars" to not copy the last
      ' byte.  However, NumChars is described as an integer whereas Position is
      ' described as Long. I was concerned by "integer" they mean 16 bits.
      'Debug.Print BinaryStream.Position
      BinaryStream.Position = BinaryStream.Position - 1
      BinaryStream.SetEOS
      'Debug.Print BinaryStream.Position
    
      UTFStream.Flush
      UTFStream.Close
      Set UTFStream = Nothing
    
      BinaryStream.SaveToFile PathFileName, adSaveCreateOverWrite
      BinaryStream.Flush
      BinaryStream.Close
      Set BinaryStream = Nothing
    
    End Sub

    Nueva versión de la rutina de

    Esta versión omite el código para descartar los no deseados LF añade al final porque se evita la adición de la LF en el primer lugar. Me han retenido la versión original en caso de que alguien esté interesado en la técnica para eliminar los caracteres finales.

    Public Sub PutTextFileUtf8NoBOM(ByVal PathFileName As String, ByVal FileBody As String)
    
      ' Outputs FileBody as a text file named PathFileName using
      ' UTF-8 encoding without leading BOM
    
      ' Needs reference to "Microsoft ActiveX Data Objects n.n Library"
      ' Addition to original code says version 2.5. Tested with version 6.1.
    
      '  1Nov16  Copied from http://stackoverflow.com/a/4461250/973283
      '          but replaced literals with parameters.
      ' 15Aug17  Discovered routine was adding an LF to the end of the file.
      '          Added code to discard that LF.
      ' 11Oct17  Posted to StackOverflow
      '  9Aug18  Comment from rellampec suggested removal of adWriteLine from
      '          WriteTest statement would avoid adding LF.
      ' 30Sep18  Amended routine to remove adWriteLine from WriteTest statement
      '          and code to remove LF from file. Successfully tested new version.
    
      ' References: http://stackoverflow.com/a/4461250/973283
      '             https://www.w3schools.com/asp/ado_ref_stream.asp
    
      Dim BinaryStream As Object
      Dim UTFStream As Object
    
      Set UTFStream = CreateObject("adodb.stream")
    
      UTFStream.Type = adTypeText
      UTFStream.Mode = adModeReadWrite
      UTFStream.Charset = "UTF-8"
      UTFStream.Open
      UTFStream.WriteText FileBody
    
      UTFStream.Position = 3 'skip BOM
    
      Set BinaryStream = CreateObject("adodb.stream")
      BinaryStream.Type = adTypeBinary
      BinaryStream.Mode = adModeReadWrite
      BinaryStream.Open
    
      UTFStream.CopyTo BinaryStream
    
      UTFStream.Flush
      UTFStream.Close
      Set UTFStream = Nothing
    
      BinaryStream.SaveToFile PathFileName, adSaveCreateOverWrite
      BinaryStream.Flush
      BinaryStream.Close
      Set BinaryStream = Nothing
    
    End Sub
    • Descubrí tu rutina añade un LF al final del archivo. Me interesa sus comentarios en mi variación de su rutina.
    • Lo siento, pero yo no he escrito en VBScript durante años, así que no puedo comentar el código. Pero si el código de direcciones de su problema específico, creo que ya está bien 😉
    • :@user272735 entiendo tu problema. Se le preguntó sobre los puntos más finos de código que escribí hace años es uno de mis mascotas odia. Mi comentario fue principalmente para avisarle de mi post que era una actualización de la suya.
    • Quizás me he perdido algo, pero la LineFeed es añadido por adWriteLine, que se puede aplicar a ti mismo por solo FileBody & vbLf. Este puede ayudar como referencia. Si el propósito es tener la FileBody con sólo \n o Feed Line breakers, el camino a seguir es un replace de vbCrLf por vbLf antes de escribir a la corriente. De hecho, LineSeparator se utiliza para identificar las líneas sólo cuando leer de la corriente.
    • Gracias por tu comentario. La relectura de la http://www.w3schools.com especificación veo adWriteLine es opcional que no había notado antes. Voy a probar esto y que le informe en un día o dos.
  5. 0

    Uf prefiere nativo de T-SQL en lugar de código externo

    DECLARE @FILE_NAME              VARCHAR(255)    = 'd:\utils\test.xml'       --drive:\path\filename\
    DECLARE @FILE_DATA              VARCHAR(MAX)    = '<?xml version="1.0" encoding="UTF-8"?>test</xml>'            --binary as varchar(max)
    
    DECLARE @FILE_NAME_TO           VARCHAR(255)                        --Temp name for text stream
    DECLARE @FSO_ID_TXTSTRM         INT                                 --Text Stream
    DECLARE @FSO_ID_BINSTRM         INT                                 --Binary Stream
    DECLARE @RC                     INT 
    
    EXEC @RC = sp_OACreate 'ADODB.Stream',  @FSO_ID_TXTSTRM OUTPUT
    EXEC @RC = sp_OASetProperty             @FSO_ID_TXTSTRM,    'Type',             2                           --1 = binary, 2 = text
    EXEC @RC = sp_OASetProperty             @FSO_ID_TXTSTRM,    'Mode',             3                           --0 = not set, 1 read, 2 write, 3 read/write
    EXEC @RC = sp_OASetProperty             @FSO_ID_TXTSTRM,    'Charset',          'UTF-8'                     --'ISO-8859-1'
    EXEC @RC = sp_OASetProperty             @FSO_ID_TXTSTRM,    'LineSeparator',    'adLF'
    EXEC @RC = sp_OAMethod                  @FSO_ID_TXTSTRM,    'Open'  
    EXEC @RC = sp_OAMethod                  @FSO_ID_TXTSTRM,    'WriteText',        NULL,       @FILE_DATA      --text method
    
    --Create binary stream
    EXEC @RC = sp_OACreate 'ADODB.Stream',  @FSO_ID_BINSTRM OUTPUT
    EXEC @RC = sp_OASetProperty             @FSO_ID_BINSTRM,    'Type',             1                           --1 = binary, 2 = text
    EXEC @RC = sp_OAMethod                  @FSO_ID_BINSTRM,    'Open'
    EXEC @RC = sp_OASetProperty             @FSO_ID_BINSTRM,    'Mode',             3                           --0 = not set, 1 read, 2 write, 3 read/write    
    
    --Move 3 positions forward in text stream (BOM is first 3 positions)
    EXEC @RC = sp_OASetProperty             @FSO_ID_TXTSTRM,    'Position',         3
    
    --Copy text stream to binary stream
    EXEC @RC = sp_OAMethod                  @FSO_ID_TXTSTRM,    'CopyTo',           NULL,       @FSO_ID_BINSTRM
    
    --Commit data and close text stream
    EXEC @RC = sp_OAMethod                  @FSO_ID_TXTSTRM,    'Flush'
    EXEC @RC = sp_OAMethod                  @FSO_ID_TXTSTRM,    'Close'
    EXEC @RC = sp_OADestroy                 @FSO_ID_TXTSTRM
    
    --Save binary stream to file and close
    EXEC @RC = sp_OAMethod                  @FSO_ID_BINSTRM,    'SaveToFile',       NULL,       @FILE_NAME, 2   --1 = notexist 2 = overwrite
    EXEC @RC = sp_OAMethod                  @FSO_ID_BINSTRM,    'Close'
    EXEC @RC = sp_OADestroy                 @FSO_ID_BINSTRM
  6. 0

    Aquí otra lista de materiales de desecho de hack, de una respuesta que se superpone a su pregunta.

    Disculpas por la tardanza en contestar – esto es más para otras personas que están encontrando el Orden de Bytes de los Marcadores y las páginas vistas en esta pregunta me dicen que tu pregunta es relevante para varios de los problemas relacionados con: es sorprendente lo difícil que es escribir una lista de materiales de archivo Libres en VBA – incluso algunos de los flujos de bibliotecas de depósito de una lista de materiales en su salida, si pidió o no.

    Digo que mi respuesta «se superpone’ porque el código de abajo es la solución de un problema un poco diferente – el propósito principal es la escritura de un archivo de Esquema de una carpeta con una heterogénea colección de archivos – pero es un ejemplo de trabajo de BOM retiro y la lista de materiales de archivo libres de escribir en, y el segmento correspondiente está claramente marcada.

    La funcionalidad clave es que hemos de recorrer todos los ‘.csv’ los archivos en una carpeta, y ponemos a prueba cada archivo con un rápido mordisco de los primeros cuatro bytes: y nosotros sólo emprender la enorme tarea de desnudar a cabo el marcador si vemos uno.

    Estamos trabajando con archivos de bajo nivel-código de manipulación de la primordial C. Tenemos, todo el camino hacia abajo para el uso de matrices de bytes, ya que todo lo demás que haces en VBA depósito de la Orden de Bytes de Marcadores incrustado en la estructura de una variable de cadena.

    Así, sin más adodb, aquí está el código:

    Lista de materiales de Desecho de código para los archivos de texto en un esquema.archivo ini:

    Public Sub SetSchema(strFolder Como Cadena) 
    On Error Resume Next 
    'Escribir un Esquema.archivo ini a la carpeta de datos.
    'Esto es necesario si no tenemos el registro de los privilegios para establecer el 'correcta 'de ImportMixedTypes=' Texto de registro de valor, lo que invalida IMEX=1
    'El código también comprueba para ANSI o UTF-8 y UTF-16 archivos, y se aplica un 'valor utilizable para el conjunto de caracteres ( UNICODE|ANSI), con un horrible hack.
    'OEM de la página de códigos definidos por el texto no es compatible: más de la codificación es necesaria
    '...Y lo tira fuera de Orden de Bytes de los Marcadores, si los vemos - la OLEDB SQL 'proveedor para textfiles no se puede tratar con una lista de materiales en una o UTF-16, UTF-8 archivo
    'No implementado: el manejo de los archivos delimitados por tabulaciones u otros delimitadores. El 'código supone una fila de encabezado de las columnas, especifica 'escanear todas las filas', y 'impone 'leer la columna de texto' si los tipos de datos son mixtos.
    Dim strSchema Como Cadena Dim strFile Como Cadena Dim hndFile siempre Dim arrFile() As Byte Dim arrBytes(0 A 4) Como Byte
    Si la Derecha(strFolder, 1) <> "\", a Continuación, strFolder = strFolder & "\"
    'Dir() es una función de iterador al llamar con un comodín:
    strFile = VBA.El sistema de ficheros.Dir(strFolder & "*.csv")
    Do while Len(strFile) > 0
    hndFile = FreeFile Abierto strFolder & strFile For Binary As #hndFile Get #hndFile, , arrBytes Cerca de #hndFile
    strSchema = strSchema & "[" & strFile & "]" & vbCrLf strSchema = strSchema & "Formato=CSVDelimited" & vbCrLf strSchema = strSchema & "ImportMixedTypes=Texto" & vbCrLf strSchema = strSchema & "MaxScanRows=0" & vbCrLf
    Si arrBytes(2) = 0 O arrBytes(3) = 0 then ' este es un hack strSchema = strSchema & "conjunto de caracteres=UNICODE" & vbCrLf Otra cosa strSchema = strSchema & "conjunto de caracteres=ANSI" & vbCrLf End If
    strSchema = strSchema & "ColNameHeader = True" & vbCrLf strSchema = strSchema & vbCrLf
    '***********************************************************
    'Lista de materiales de la evacuación de marca de orden de Byte romper el Acceso OLEDB texto proveedor de:
    Si arrBytes(0) = &HFE Y arrBytes(1) = &HFF _ O arrBytes(0) = &HFF Y arrBytes(1) = &HFE Luego
    hndFile = FreeFile Abierto strFolder & strFile For Binary As #hndFile ReDim arrFile(de 0 A LOF(hndFile) - 1) Get #hndFile, , arrFile Cerca de #hndFile
    BigReplace arrFile, arrBytes(0) & arrBytes(1), ""
    hndFile = FreeFile Abierto strFolder & strFile For Binary As #hndFile Put #hndFile, , arrFile Cerca de #hndFile Borrar arrFile
    ElseIf arrBytes(0) = &HEF Y arrBytes(1) = &HBB Y arrBytes(2) = &HBF a Continuación
    hndFile = FreeFile Abierto strFolder & strFile For Binary As #hndFile ReDim arrFile(de 0 A LOF(hndFile) - 1) Get #hndFile, , arrFile Cerca de #hndFile BigReplace arrFile, arrBytes(0) & arrBytes(1) & arrBytes(2), ""
    hndFile = FreeFile Abierto strFolder & strFile For Binary As #hndFile Put #hndFile, , arrFile Cerca de #hndFile Borrar arrFile
    End If
    '***********************************************************

    strFile = "" strFile = Dir
    Bucle
    Si Len(strSchema) > 0, Entonces
    strFile = strFolder & "Esquema.ini"
    hndFile = FreeFile Abierto strFile For Binary As #hndFile Put #hndFile, , strSchema Cerca de #hndFile
    End If

    End Sub

    Public Sub BigReplace(ByRef arrBytes() As Byte, _ ByRef SearchFor As String, _ ByRef ReplaceWith Como Cadena) On Error Resume Next
    Dim varSplit Como Variante
    varSplit = Split(arrBytes, SearchFor) arrBytes = Unirse a$(varSplit, ReplaceWith)
    Borrar varSplit
    End Sub

    El código más fácil de entender si se sabe que una Matriz de Bytes puede ser asignado a una de VBA.Cadena, y viceversa. El BigReplace() la función es un hack que deja de lado algunos de VBA ineficiente manejo de cadenas, especialmente de asignación: usted encontrará que los archivos grandes causar serios de memoria y problemas de rendimiento si hacerlo de cualquier otra manera.

Dejar respuesta

Please enter your comment!
Please enter your name here