cargar csv en hoja Propuesta con dudas

26/12/2007 - 03:24 por Ivan | Informe spam
hola a todos,

lo 1º, felices fiestas. Espero que todos disfruteis en compañia de la gente que os importa

a raiz de una respuesta a una consulta sobre como cargar en una hoja, a partir de la 1ª fila libre, el contenido de otra
hoja (o parte de el) guardada como CSV, (texto separado con comas), me puse a investigar un poco los csv, con los que
nunca habia trabajado, y el resultado fue la propuesta que pongo al final, lo suficientemente generica para poder ser
utilizada en bastantes situaciones diferentes.

parece no trabajar mal en los supuestos para los que esta hecha, pero me han surgido varias dudas sobre el tema que
quizas podais aclararme un poco:

.-> lo 1º que me ha llamado la atencion es que las supuestas comas separadoras, y al menos en mis pruebas, en realidad
son punto y coma. Supongo que el motivo sera para diferenciarlo del separador decimal, que he creido entender que en los
csv es la coma, independientemente de la configuracion del usuario para dicho separador.

¿esto es normal o es consecuencia/depende de alguna manipulacion en opciones o similar, o pej. a que se use el ultimo
separador elegido en alguna operacion de guardado de archivos de texto via macros?

.->2º) ¿es posible buscar un dato en el csv antes de cargarlo en la hoja, es decir dentro del propio csv?

en este caso concreto se trataba de buscar una fecha (la del dia en curso) y cargar solo los registros coincidentes en
la hoja. En mi caso lo solucione cargando el archivo completo en una nueva hoja, hacer aqui la busqueda y carga y
eliminando la hoja acto seguido, pero supongo que si existe la posibilidad de realizar la busqueda previamente, se
ahorrarian bastantes pasos

algo asi como si se leyera con input y solo se cargaran los registros adecuados, pero con querytables

.->3º) el codigo de carga esta sacado de grabar una macro, y aunque he eliminado lo que me parecia superfluo hay unas
cuantas cosas que no me he atrevido a tocar por si acaso ¿hay algun minimo de propiedades 'obligado' que haya que
declarar explicitamnete para asegurarse un resultado llamemosle estandar?

bueno, estas son algunas de las dudas que se me ocurren.

En cuanto a los codigos, pongo tambien la respuesta explicacion que le daba al consultante, y aunque constantes usadas
para facilitar la adaptacion hagan referencia a fecha y hora, en realidad podrian valer para cualquier otro dato que se
quisiese buscar, eso si modificando el valor de la variable fecha en la 1ª macro

'***************** parte de la respuesta dada al consultante ***********************************************
..

en tu 1er mensaje hablas de buscar desde un libro en otro diferente, la fecha actual y copiar la fila que la contenga en
el primer libro

en el segundo, pides copiar el contenido de un archivo de texto (CSV) a partir de la 1ª fila libre [¿de que columna?]
del archivo que ejecuta la macro, ..., y ordenar por fecha y hora [¿en que columnas estan estos datos?]

bueno, solo para comentarte que cuando se piden detalles concretos suele ser para que lo que te den sean detalles
concretos, y no otra serie de enunciados que vuelven a dejar todo a la imaginacion del posible colaborador, y aun peor
pidiendo algo totalmente diferente al original

esto aparte, como no tengo claro lo que buscas, te he preparado dos macros.

con la 1ª ('Cargar_Fecha') te busca en un archivo csv (hoja de excel guardada como CSV) y te carga en la primera fila
libre (que especifiques) de la hoja (que especifiques) a partir de una columna [que especifiques] los registros que
contengan la fecha actul en el momento de correr la macro en un campo [que especifiques] y lo ordena por este campo y
por otro que contenga la hora [. que especifiques]

con la 2ª ('Cargar_Csv_Y_Ordenar') carga todo el contenido del archivo csv a partir de la 1ª fila libre y ordena por
fecha y hora(valgan todas las especificaciones que con la anterior)

de todas formas, para facilitarte el 'especificar' los detalles concretos te he puesto unas constantes que inicialmente,
y al menos hasta que pruebes los codigos y veas como funcionan, los entiendas y vean si se acercan a lo que buscas, son
lo unico que deberias manipular de los codigos.

las constantes tienen un comentario sobre lo que debes poner en cada una.

las dos macros van acompañadas con otros tres procedimientos que usan ellas a nivel interno, y que, aunque si las
entiendes puedes usarlas en otras muchas situaciones, inicialmente tampoco debes tocarlas

segun sea el caso llama a una de las dos macros desde el boton [que boton?¿de que barra de herramientas?] bien via
asignar macro, bien desde su evento click (depende del tipo de boton)

NOTA: es la primera vez que manipulo archivos csv, y el codigo de importacion es el resultado de adaptar una macro
grabada (cosa por cierto muy util para entenderla), con lo que no te aseguro que haya algunas cosas que puedan sobrar o
que pudiesen trabajar mejor de otra forma, pero asi a mi al menos me realizan el trabajo bastante bien


copia pega los siguientes codigos en un 'modulo' NORMAL de vba (si no sabes cuales son , dale a 'Alt+F11 => en el editor
de vb => menu insertar => Modulo (a secas) => en esta ventana es donde deberas paegar los codigos

OJO=> asegurate de que los codigos queden 'exactamente' igual a como los veas en el foro (lo unico que debes modificar
es el valor asignado a las constantes mnencionadas)

OJO bis=> si tu version es anterior al 2000 habria que replantear algunas cosas. Igualmente si es la 2007, aunque creo
que funcionara bien, tambien convendria revisar algunas cosas, sobre todo para ampliar rangos

por ultimo, prueba con copias (y paciencia)

''-
'********************* pega desde aqui *******************************
''constantes para facilitar la modificacion --
'
'> cambia "Hoja1" por el nombre de tu hoja (entre comillas)
Const Hj As String = "Hoja1"
'> cambia el 1 por el nº de la 1ª columna de la lista
Const ColInicio As Byte = 1
'> cambia el 1 por el nº de la columna de la fecha ( o dato a buscar y 1º de ordenacion)
Const ColFecha As Byte = 3
'> cambia el 2 por el nº de la columna de la hora (o por el 2º criterio de ordenacion)
Const ColHora As Byte = 2
'> cambia por False si tu lista no tiene fila de titulos
Const ConFilaTitulos As Boolean = True
'*************************************************************
''->>> una de estas 2 primeras macros la debes llamar desde el boton <<<-
'--
'-> esta macro carga solo los registros coincidentes con el dia actual
'
Sub Cargar_Fecha()
Dim Archivo As String, uCol As Byte, nCols As Byte, n As Long, _
uF As Long, wHj As Worksheet, celda As Range, Fecha
Archivo = ArchivoConRuta
If Archivo = "" Then _
MsgBox ("No se ha seleccionado ningun archivo"): Exit Sub
Fecha = Date ' puedes poner cualquier otro dato, tanto de fecha como otro
With ThisWorkbook
Set wHj = .Worksheets(Hj)
Application.ScreenUpdating = False
With .Worksheets.Add(before:=wHj)
ImportarTexto Archivo, , ColInicio, ConFilaTitulos
Ordenar ColFecha, ColHora, , ConFilaTitulos
If Application.CountIf(.Columns(ColFecha), Fecha) > 0 Then
Set celda = .Columns(ColFecha).Find(Fecha, .Cells(1, ColFecha), _
xlValues, xlWhole): n = celda.Row: uF = n
uCol = celda.CurrentRegion.Columns.Count + ColInicio - 1
Do While .Cells(uF + 1, ColFecha) = celda
uF = uF + 1
Loop
.Range(.Cells(n, ColInicio), .Cells(uF, uCol)) _
.Copy wHj.Cells(65536, ColInicio).End(xlUp).Offset(1)
Set celda = Nothing
Ordenar ColFecha, ColHora, wHj, ConFilaTitulos
MsgBox "La lista se ha actualizado satisfactoriamente"
Else
MsgBox "No se ha encontrado la fecha indicada."
End If
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
End With
End With
Set wHj = Nothing
End Sub
'-
'> esta macro carga todo el contenido de el archivo CSV --
'
Sub Cargar_Csv_Y_Ordenar()
Dim Archivo As String, ultFila As Long, wHj As Worksheet
Archivo = ArchivoConRuta
If Archivo = "" Then _
MsgBox ("No se ha seleccionado ningun archivo"): Exit Sub
Set wHj = ThisWorkbook.Worksheets(Hj)
ultFila = wHj.Cells(65536, ColInicio).End(xlUp).Row
ImportarTexto Archivo, wHj, ColInicio, ConFilaTitulos
If wHj.Cells(65536, ColInicio).End(xlUp).Row = ultFila Then Exit Sub
Ordenar ColFecha, ColHora, wHj, ConFilaTitulos
MsgBox "La lista se ha actualizado satisfactoriamente"
Set wHj = Nothing
End Sub
'************* funcion y codigo usados en las macros *******************
''
'-> devuelve el nombre mas la ruta completa del archivo seleccionado --
' en un cuadro de dialogo. OJO: creo que FileDialog no esta disponible
' para las versiones previas al 2000
'
Function ArchivoConRuta() As String
With Application.FileDialog(msoFileDialogFilePicker)
If .Show = -1 Then ArchivoConRuta = .SelectedItems(1)
End With
End Function
'-
'-> carga el archivo de texto segun los argumentos pasados
'
Sub ImportarTexto(Ruta_Y_Archivo As String, _
Optional Hoja As Worksheet = Nothing, _
Optional Columna_Ini As Byte = 1, _
Optional Titulos As Boolean = True)
On Error GoTo ImportarTexto_Error
If Hoja Is Nothing Then Set Hoja = ActiveSheet
With Hoja.QueryTables.Add(Connection:= _
"TEXT;" & Ruta_Y_Archivo, Destination:= _
Hoja.Cells(65536, Columna_Ini).End(xlUp).Offset(1))
.PreserveFormatting = True
.RefreshStyle = xlInsertEntireRows
.TextFileStartRow = 1 - (Titulos)
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = True
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.AdjustColumnWidth = True
.Refresh BackgroundQuery:=False
.Delete
End With
On Error GoTo 0
Exit Sub
ImportarTexto_Error:
MsgBox "No se ha podido cargar el archivo: " & vbCr & _
Ruta_Y_Archivo & "." & vbCr & vbCr & _
"Comprueba que es un archivo correcto."
End Sub
''
'-> ordena una lista en base a las dos columnas pasadas
'
Sub Ordenar(Optional Orden_1 As Byte = 1, _
Optional Orden_2 As Byte = 2, _
Optional Hj_Orden As Worksheet = Nothing, _
Optional Titulos As Boolean = True)
Dim pFila As Long
If Hj_Orden Is Nothing Then Set Hj_Orden = ActiveSheet
On Error Resume Next
With Hj_Orden.Cells(65536, Orden_1).End(xlUp).CurrentRegion
pFila = .Cells(1).Row - (Titulos = True)
.Sort Key1:=Hj_Orden.Cells(pFila, Orden_1), Order1:=xlAscending, _
Key2:=Hj_Orden.Cells(pFila, Orden_2), Order2:=xlAscending, _
Header:=Titulos
End With
End Sub
''******************** pega hasta aqui ****************************************


bueno, si podeis aclarame alguna duda os lo agradezco, y si quereis comentar/proponer cualquier cosa y o modificacion
sobre los codigos, o cualquier otra alternativa, sera bien recibido

un saludo
Ivan

PD: ojo a los posibles trunque del codigo en el editor del foro
 

Leer las respuestas

#1 Xavier Budet Graco
26/12/2007 - 12:08 | Informe spam
Hola Ivan, no sé si utilizaré tus proposiciones o respuestas (no he usado nunca archivos CSV), pero lo guardo porque me parece interesante. Gracias.

Saludos,

Xavier

Quitar MAC para contestar. Gracias.


"Ivan" escribió en el mensaje news:es%
hola a todos,

lo 1º, felices fiestas. Espero que todos disfruteis en compañia de la gente que os importa

a raiz de una respuesta a una consulta sobre como cargar en una hoja, a partir de la 1ª fila libre, el contenido de otra
hoja (o parte de el) guardada como CSV, (texto separado con comas), me puse a investigar un poco los csv, con los que
nunca habia trabajado, y el resultado fue la propuesta que pongo al final, lo suficientemente generica para poder ser
utilizada en bastantes situaciones diferentes.

parece no trabajar mal en los supuestos para los que esta hecha, pero me han surgido varias dudas sobre el tema que
quizas podais aclararme un poco:

.-> lo 1º que me ha llamado la atencion es que las supuestas comas separadoras, y al menos en mis pruebas, en realidad
son punto y coma. Supongo que el motivo sera para diferenciarlo del separador decimal, que he creido entender que en los
csv es la coma, independientemente de la configuracion del usuario para dicho separador.

¿esto es normal o es consecuencia/depende de alguna manipulacion en opciones o similar, o pej. a que se use el ultimo
separador elegido en alguna operacion de guardado de archivos de texto via macros?

.->2º) ¿es posible buscar un dato en el csv antes de cargarlo en la hoja, es decir dentro del propio csv?

en este caso concreto se trataba de buscar una fecha (la del dia en curso) y cargar solo los registros coincidentes en
la hoja. En mi caso lo solucione cargando el archivo completo en una nueva hoja, hacer aqui la busqueda y carga y
eliminando la hoja acto seguido, pero supongo que si existe la posibilidad de realizar la busqueda previamente, se
ahorrarian bastantes pasos

algo asi como si se leyera con input y solo se cargaran los registros adecuados, pero con querytables

.->3º) el codigo de carga esta sacado de grabar una macro, y aunque he eliminado lo que me parecia superfluo hay unas
cuantas cosas que no me he atrevido a tocar por si acaso ¿hay algun minimo de propiedades 'obligado' que haya que
declarar explicitamnete para asegurarse un resultado llamemosle estandar?

bueno, estas son algunas de las dudas que se me ocurren.

En cuanto a los codigos, pongo tambien la respuesta explicacion que le daba al consultante, y aunque constantes usadas
para facilitar la adaptacion hagan referencia a fecha y hora, en realidad podrian valer para cualquier otro dato que se
quisiese buscar, eso si modificando el valor de la variable fecha en la 1ª macro

'***************** parte de la respuesta dada al consultante ***********************************************
..

en tu 1er mensaje hablas de buscar desde un libro en otro diferente, la fecha actual y copiar la fila que la contenga en
el primer libro

en el segundo, pides copiar el contenido de un archivo de texto (CSV) a partir de la 1ª fila libre [¿de que columna?]
del archivo que ejecuta la macro, ..., y ordenar por fecha y hora [¿en que columnas estan estos datos?]

bueno, solo para comentarte que cuando se piden detalles concretos suele ser para que lo que te den sean detalles
concretos, y no otra serie de enunciados que vuelven a dejar todo a la imaginacion del posible colaborador, y aun peor
pidiendo algo totalmente diferente al original

esto aparte, como no tengo claro lo que buscas, te he preparado dos macros.

con la 1ª ('Cargar_Fecha') te busca en un archivo csv (hoja de excel guardada como CSV) y te carga en la primera fila
libre (que especifiques) de la hoja (que especifiques) a partir de una columna [que especifiques] los registros que
contengan la fecha actul en el momento de correr la macro en un campo [que especifiques] y lo ordena por este campo y
por otro que contenga la hora [. que especifiques]

con la 2ª ('Cargar_Csv_Y_Ordenar') carga todo el contenido del archivo csv a partir de la 1ª fila libre y ordena por
fecha y hora(valgan todas las especificaciones que con la anterior)

de todas formas, para facilitarte el 'especificar' los detalles concretos te he puesto unas constantes que inicialmente,
y al menos hasta que pruebes los codigos y veas como funcionan, los entiendas y vean si se acercan a lo que buscas, son
lo unico que deberias manipular de los codigos.

las constantes tienen un comentario sobre lo que debes poner en cada una.

las dos macros van acompañadas con otros tres procedimientos que usan ellas a nivel interno, y que, aunque si las
entiendes puedes usarlas en otras muchas situaciones, inicialmente tampoco debes tocarlas

segun sea el caso llama a una de las dos macros desde el boton [que boton?¿de que barra de herramientas?] bien via
asignar macro, bien desde su evento click (depende del tipo de boton)

NOTA: es la primera vez que manipulo archivos csv, y el codigo de importacion es el resultado de adaptar una macro
grabada (cosa por cierto muy util para entenderla), con lo que no te aseguro que haya algunas cosas que puedan sobrar o
que pudiesen trabajar mejor de otra forma, pero asi a mi al menos me realizan el trabajo bastante bien


copia pega los siguientes codigos en un 'modulo' NORMAL de vba (si no sabes cuales son , dale a 'Alt+F11 => en el editor
de vb => menu insertar => Modulo (a secas) => en esta ventana es donde deberas paegar los codigos

OJO=> asegurate de que los codigos queden 'exactamente' igual a como los veas en el foro (lo unico que debes modificar
es el valor asignado a las constantes mnencionadas)

OJO bis=> si tu version es anterior al 2000 habria que replantear algunas cosas. Igualmente si es la 2007, aunque creo
que funcionara bien, tambien convendria revisar algunas cosas, sobre todo para ampliar rangos

por ultimo, prueba con copias (y paciencia)

''-
'********************* pega desde aqui *******************************
''constantes para facilitar la modificacion --
'
'> cambia "Hoja1" por el nombre de tu hoja (entre comillas)
Const Hj As String = "Hoja1"
'> cambia el 1 por el nº de la 1ª columna de la lista
Const ColInicio As Byte = 1
'> cambia el 1 por el nº de la columna de la fecha ( o dato a buscar y 1º de ordenacion)
Const ColFecha As Byte = 3
'> cambia el 2 por el nº de la columna de la hora (o por el 2º criterio de ordenacion)
Const ColHora As Byte = 2
'> cambia por False si tu lista no tiene fila de titulos
Const ConFilaTitulos As Boolean = True
'*************************************************************
''->>> una de estas 2 primeras macros la debes llamar desde el boton <<<-
'--
'-> esta macro carga solo los registros coincidentes con el dia actual
'
Sub Cargar_Fecha()
Dim Archivo As String, uCol As Byte, nCols As Byte, n As Long, _
uF As Long, wHj As Worksheet, celda As Range, Fecha
Archivo = ArchivoConRuta
If Archivo = "" Then _
MsgBox ("No se ha seleccionado ningun archivo"): Exit Sub
Fecha = Date ' puedes poner cualquier otro dato, tanto de fecha como otro
With ThisWorkbook
Set wHj = .Worksheets(Hj)
Application.ScreenUpdating = False
With .Worksheets.Add(before:=wHj)
ImportarTexto Archivo, , ColInicio, ConFilaTitulos
Ordenar ColFecha, ColHora, , ConFilaTitulos
If Application.CountIf(.Columns(ColFecha), Fecha) > 0 Then
Set celda = .Columns(ColFecha).Find(Fecha, .Cells(1, ColFecha), _
xlValues, xlWhole): n = celda.Row: uF = n
uCol = celda.CurrentRegion.Columns.Count + ColInicio - 1
Do While .Cells(uF + 1, ColFecha) = celda
uF = uF + 1
Loop
.Range(.Cells(n, ColInicio), .Cells(uF, uCol)) _
.Copy wHj.Cells(65536, ColInicio).End(xlUp).Offset(1)
Set celda = Nothing
Ordenar ColFecha, ColHora, wHj, ConFilaTitulos
MsgBox "La lista se ha actualizado satisfactoriamente"
Else
MsgBox "No se ha encontrado la fecha indicada."
End If
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
End With
End With
Set wHj = Nothing
End Sub
'-
'> esta macro carga todo el contenido de el archivo CSV --
'
Sub Cargar_Csv_Y_Ordenar()
Dim Archivo As String, ultFila As Long, wHj As Worksheet
Archivo = ArchivoConRuta
If Archivo = "" Then _
MsgBox ("No se ha seleccionado ningun archivo"): Exit Sub
Set wHj = ThisWorkbook.Worksheets(Hj)
ultFila = wHj.Cells(65536, ColInicio).End(xlUp).Row
ImportarTexto Archivo, wHj, ColInicio, ConFilaTitulos
If wHj.Cells(65536, ColInicio).End(xlUp).Row = ultFila Then Exit Sub
Ordenar ColFecha, ColHora, wHj, ConFilaTitulos
MsgBox "La lista se ha actualizado satisfactoriamente"
Set wHj = Nothing
End Sub
'************* funcion y codigo usados en las macros *******************
''
'-> devuelve el nombre mas la ruta completa del archivo seleccionado --
' en un cuadro de dialogo. OJO: creo que FileDialog no esta disponible
' para las versiones previas al 2000
'
Function ArchivoConRuta() As String
With Application.FileDialog(msoFileDialogFilePicker)
If .Show = -1 Then ArchivoConRuta = .SelectedItems(1)
End With
End Function
'-
'-> carga el archivo de texto segun los argumentos pasados
'
Sub ImportarTexto(Ruta_Y_Archivo As String, _
Optional Hoja As Worksheet = Nothing, _
Optional Columna_Ini As Byte = 1, _
Optional Titulos As Boolean = True)
On Error GoTo ImportarTexto_Error
If Hoja Is Nothing Then Set Hoja = ActiveSheet
With Hoja.QueryTables.Add(Connection:= _
"TEXT;" & Ruta_Y_Archivo, Destination:= _
Hoja.Cells(65536, Columna_Ini).End(xlUp).Offset(1))
.PreserveFormatting = True
.RefreshStyle = xlInsertEntireRows
.TextFileStartRow = 1 - (Titulos)
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = True
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.AdjustColumnWidth = True
.Refresh BackgroundQuery:=False
.Delete
End With
On Error GoTo 0
Exit Sub
ImportarTexto_Error:
MsgBox "No se ha podido cargar el archivo: " & vbCr & _
Ruta_Y_Archivo & "." & vbCr & vbCr & _
"Comprueba que es un archivo correcto."
End Sub
''
'-> ordena una lista en base a las dos columnas pasadas
'
Sub Ordenar(Optional Orden_1 As Byte = 1, _
Optional Orden_2 As Byte = 2, _
Optional Hj_Orden As Worksheet = Nothing, _
Optional Titulos As Boolean = True)
Dim pFila As Long
If Hj_Orden Is Nothing Then Set Hj_Orden = ActiveSheet
On Error Resume Next
With Hj_Orden.Cells(65536, Orden_1).End(xlUp).CurrentRegion
pFila = .Cells(1).Row - (Titulos = True)
.Sort Key1:=Hj_Orden.Cells(pFila, Orden_1), Order1:=xlAscending, _
Key2:=Hj_Orden.Cells(pFila, Orden_2), Order2:=xlAscending, _
Header:=Titulos
End With
End Sub
''******************** pega hasta aqui ****************************************


bueno, si podeis aclarame alguna duda os lo agradezco, y si quereis comentar/proponer cualquier cosa y o modificacion
sobre los codigos, o cualquier otra alternativa, sera bien recibido

un saludo
Ivan

PD: ojo a los posibles trunque del codigo en el editor del foro





Preguntas similares