Address y Nº de Areas

21/05/2007 - 04:33 por Ivan | Informe spam
hola a todos,

estoy estudiando un poco la propiedad Areas del objeto range, y me ha surjido una duda/inconveniente

al intentar cargar con address las referencias de las celdas visibles tras un filtrado en un string, me he encontrado
con que solo me carga hasta que el string tiene como mucho 256 caracteres, que para referncias relativas (0,0) supone
+/- 52 refencias (con las absolutas todavia menos) de las casi 1400 areas existentes en mi ej.

al principio pense que era el limite maximo de areas que se podian manejar, pero tras varias pruebas he comprobado que
el nº de areas si es correcto (1398), con lo que he pendsado que el que tiene la limitacion es la cadena devuelta por
Addrees, pero por mas que he mirado en la ayuda no veo nada que me aclaree este punto, mucho mas cuando si reyeno un
string con esas referencias mediante un bucle si las acepta todas

al final las he cargado en una matriz, pero esto me obliga a ralentiza mucho el codigo, pues primero hay que introducir
con un bucle todas las ref, visibles, para luego tener que realizar un segundo bucle de extrccion (este si creo que es
inevitable

lo dicho;¿ hay alguna manera de almacenar en una variable todas las ref. de areas aunqu exceda las 256 sin tener que
hacer un bucle? para poder pasarselo al siguiente bucle y asi ganar un poco de tiempo ¿donde/porque esta limitacion
de caracteres?

muchas gracias de antemano y hasta pronto
un saludo
Ivan

Preguntas similare

Leer las respuestas

#1 Héctor Miguel
21/05/2007 - 05:46 | Informe spam
hola, Ivan !

... estudiando... la propiedad Areas... una duda/inconveniente
... cargar con address las referencias de las celdas visibles tras un filtrado en un string
... solo me carga hasta que el string tiene como mucho 256 caracteres... de las casi 1400 areas existentes en mi ej.
... pense que era el limite maximo de areas que se podian manejar, pero... el no de areas si es correcto (1398)
... he pendsado que el que tiene la limitacion es la cadena devuelta por Addrees
... por mas que he mirado en la ayuda no veo nada que me aclaree este punto
... mucho mas cuando si reyeno un string con esas referencias mediante un bucle si las acepta todas
... al final las he cargado en una matriz, pero esto me obliga a ralentiza mucho el codigo
... primero... introducir con un bucle todas las ref, visibles... luego... un segundo bucle de extraccion (este si creo que es inevitable
... hay alguna manera de almacenar en una variable todas las ref. de areas aunqu exceda las 256 sin tener que hacer un bucle? ...



1) con respecto a la 'capacidad' de contencion de una variable de tipo string, lo siguiente es un extracto de la ayuda en linea:
" La tabla siguiente muestra los tipos de datos compatibles, incluyendo el tama#o de almacenamiento y el intervalo."
"Tipo de datos Tama#o de almacenamiento Intervalo"
"String (longitud variable) 10 bytes + longitud de la cadena Desde 0 a 2,000 millones"
"String (longitud fija) Longitud de la cadena Desde 1 a 65,400 aproximadamente"
-> [creo que] mas bien hay que considerar la memoria que sera 'reservada' y utilizar el tipo de datos mas 'apropiado' -?-

2) con relacion al objeto 'Areas' y la propiedad 'Areas', otro extracto de la ayuda en linea dice:

a) "Objeto de conjunto Areas"
"Un conjunto de las areas, o bloques de celdas contiguas, de una seleccion."
"No existe un objeto Area singular; los elementos individuales del conjunto Areas son objetos Range."
"El conjunto Areas contiene un objeto Range por cada rango de celdas discretas y contiguas de una seleccion."
"Si la seleccion contiene una sola area, el conjunto Areas contendra un unico objeto Range que correspondera a esa seleccion."
=> OJO con el siguiente:
"Algunas operaciones no pueden realizarse en mas de un area a la vez de la misma seleccion"
"debe ejecutar un bucle en las areas individuales de la seleccion y ejecutar las operaciones en cada area por separado."

b) "Propiedad Areas"
"Devuelve un conjunto Areas que representa todos los rangos de una seleccion de varias areas. Es de solo lectura."
"Para obtener mas informacion acerca de como devolver un solo elemento de un conjunto, vea Devolver un objeto de un conjunto."
"Comentarios"
"En una seleccion sencilla, la propiedad Areas devuelve un conjunto de un solo objeto, el propio objeto original Range."
"En una seleccion de varias areas, el metodo devuelve un conjunto que contiene un objeto por cada area seleccionada."

3) [tratando de hacer un] 'resumen'...
a) 'Areas' resulta ser un *conjunto* de objetos Range [puede ser unico o multiple, segun el numero de rangos NO-contiguos]
b) la limitante de ~256 caracteres [o string] es aplicable bajo otro contexto [p.e. caracteres en formulas para validaciones, etc.]
c) existe un limite para *seleccionar* un rango *multiple* de ~2,048 [o rangos no-contiguos]

4) [probablemente] te resultara de mayor 'rapidez' usar los filtros avanzados [copiando a otro lugar]
y rellenar algun objeto [matriz o control de lista/combo] 'directamente' con el resultado del filtro [rango/referencia/...]
[obviamente, ajustando o re/dimensionando primero las filas/columnas necesarias en 'el objeto' segun el resultado obtenido] -?-

si cualquier duda [o informacion adicional]... comentas ?
saludos,
hector.
Respuesta Responder a este mensaje
#2 Ivan
22/05/2007 - 02:44 | Informe spam
hola Hector Miguel, gracias por tu ayuda una vez mas

he de confesar que, por una vez, antes de enviar la consulta habia leido/repasado en la ayuda los temas que mencionas,
incluso en cierta forma son la causa de la misma. Te comento 'entre tus lineas'::

1) con respecto a la 'capacidad' de contencion de una variable de tipo string



precisamente debido a los maximos expuestos, no le veo el sentido al tope que me pone de 256 (o 254/255 depende de como
cuadren las referencias para no salirse de las 256) al cargar el string con este codigo, que creo que te sonara:

With Range([a1], [a65536].End(xlUp))
.AdvancedFilter xlFilterInPlace, , , True
donde = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Address(0, 0)

mas aun viendo que haciendo un bucle por las areas de esta forma:

with .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
for n = 1 to .Areas.Count
donde = donde & "," & .Areas(n).Address(0,0)

si me carga todas las areas (en este caso 1396)

es posible que este comentiendo algun error, pero no logro verlo, de ahí la pregunta sobre los limites del nº de
referencias discontinuas/areas devueltas por address, pues si no hay una limitacion, no acabo de ver donde esta el
problema, aun mas al saber, gracias a ti, que no se llega a el maximo nº de areas permitidas en una seleccion (que era
otro de los motivos de mi consulta, y despues te comento)

para terminar con este 1er punto, permiteme una salida de tema, pues has tocado otra de esas dudas que no se muy bien
donde buscar para aclararla. Se trata de las cadenas de longitud fija y/o variable, y este comentario tuyo:

hay que considerar la memoria que sera 'reservada' y utilizar el tipo de datos mas 'apropiado'



¿hay alguna forma de declarar una u otra diferenciadamente, o es la propia aplicacion la que discrimina que tipo aplicar
en base a las circunstancias? lo digo sobre todo porque, aunque hace tiempo que no lo miro, si recuerdo haber intentado
encontrar ayuda al respecto y apenas he encontrado poco mas que lo que mencionas


c) existe un limite para *seleccionar* un rango *multiple* de ~2,048 [o rangos no-contiguos]



muchas gracias por el dato, aunque me sonaba habertelo 'oido' mencionar en alguna de tus respuestas del foro, no lograba
encontrarlo, ni en el foro ni en la ayuda.

ahora (como siempre) me surge otra duda, que quizas solamente sea una cuestion semantica, pero por si acaso ahí va:

que quieres decir exactamente con ->>>> limite para *seleccionar* <<<<

tomandolo textualmente yo entenderia que ese limite no existe para *trabajar* con referencias multiples/discontinuas
de rangos 'no seleccionados', como de hecho (creo) hacia tu codigo y mis pruebas.

¿o es que quizas al utilizar la propiedad Areas automaticamente se seleccionan las areas implicadas? la verdad es que
esto ultimo no parece muy habitual, y de hecho (creo que) al menos visualmente el comportamiento de los rangos no es
como el de lo que generalmente entendemos como una seleccion

la verdad es que el limite de 2048 areas 'limitaria' mucho el ej. que estoy estudiando, y aqui aprovecho para enganchar
con tu ultimo punto:

4) [probablemente] te resultara de mayor 'rapidez' usar los filtros avanzados [copiando a otro lugar]



en realidad era lo que estaba haciendo (sobre todo para practicar con los filtros avanzados, ahora que he 'empezado' a
comprenderlos), pero te explico un poco los detalles del archivo: se trata de una lista de tres columnas (A ->
Codigo ->+o- asi: 100004628 /// B -> Texto -> aaaaaaa /// C -> Costo -> 6,50 )

en la 1ª columna puede haber codigos repetidos y se trataria de concatenar en la 2ª columna de un solo registro todas
las entradas de esa 2ª columna (b) para los registros con el mismo codigo ( en b el texto no es igual aunque coincida el
codigo, o al menos puede no serlo)

al final, tras unos cuantos codigos que mas o menos funcionaban el mas rapido de momento es este (para 14000 registros),
por si vieras una forma de hacerlo mas rapido (tarda entre 5 y 9 segundos, no se muy bien porque tanta diferencia siendo
el mismo codigo y las mismas (+o-) condiciones)

Sub Rellena_cuentas_6()
Dim ultF As Integer, hj As String, hj2 As String, celdaV As Range, _
ini As Integer, fin As Integer, n As Integer, f As Long, tiempo
tiempo = Timer * 1000
hj = ActiveSheet.Name: ini = 0: fin = 0
Application.ScreenUpdating = False
With ThisWorkbook
.Worksheets.Add after:=.Worksheets(.Worksheets.Count)
hj2 = ActiveSheet.Name: Range("a1:c1") = Array("Codigo", "'Texto", "Costo")
.Worksheets.Add after:=.Worksheets(.Worksheets.Count)
.Worksheets(hj).[a:c].Copy [a1]: hj = ActiveSheet.Name
End With
ultF = [a65536].End(xlUp).Row
Range("a1:c" & ultF).Sort key1:=[a2], order1:=xlAscending, header:=xlYes
With Range("a1:a" & ultF)
.AdvancedFilter xlFilterInPlace, , , True
With .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
For n = 1 To .Areas.Count
With .Areas(n)
Set celdaV = .Cells(.Rows.Count, 1)
End With
If celdaV.Row = ultF Then Exit For
ini = celdaV.Row + 1
If n < .Areas.Count Then fin = .Areas(n + 1).Cells(1, 1).Row - 1 Else fin = ultF
For f = ini To fin
celdaV.Offset(, 1) = celdaV.Offset(, 1) & " " & Range("b" & f)
Next
Set celdaV = Nothing
Next
.EntireRow.Copy Worksheets(hj2).[a2]
End With
End With
Worksheets(hj2).Columns.AutoFit
Application.DisplayAlerts = False
Worksheets(hj).Delete
Application.DisplayAlerts = True
tiempo = (Timer * 1000) - tiempo
MsgBox tiempo
End Sub

bueno, de nuevo muchas gracias y disculpa la 'barrila'. Y si te animas, cualquier explicacion/ayuda/consejo sera
bienvenido

un saludo y hasta pronto
Ivan
Respuesta Responder a este mensaje
#3 Ivan
23/05/2007 - 00:08 | Informe spam
hola de nuevo, Hector

creo que tras unas pruebas, esta parte de la consulta

tomandolo textualmente yo entenderia que ese limite no existe para *trabajar* con referencias multiples/discontinuas
de rangos 'no seleccionados', como de hecho (creo) hacia tu codigo y mis pruebas.

¿o es que quizas al utilizar la propiedad Areas automaticamente se seleccionan las areas implicadas? la verdad es que
esto ultimo no parece muy habitual, y de hecho (creo que) al menos visualmente el comportamiento de los rangos no es
como el de lo que generalmente entendemos como una seleccion

la verdad es que el limite de 2048 areas 'limitaria' mucho el ej. que estoy estudiando, .



queda (+o- y salvo apreciaciones por tu parte) resuelta.

Parece que, como era de suponer, la limitacion no afecta cuando se 'trabaja' con ref. discontinuas sin seleccionarlas
explicitamente. Al menos hasta 4600 aprox. que me devuelve el codigo sin problemas (supongo que, si no existe uno menor,
un limite razonable/inevitable sera 32268, al menos antes del 2007)

bueno, gracias de nuevo, y si tienes tiempo te agradecere cualquier aclaracion sobre el resto de las dudas

un saludo y hasta pronto
Ivan

PD: gracias tambien por el 'tip' para configurar el ' largo' de los mensajes en OE. Lo encontre en una 'charla' tuya de
alla por el 2002 (creo que en esa epoca yo no sabia casi ni lo que era un 'raton' que no fuera de carne y hueso, y no
precisamente por la edad)
Respuesta Responder a este mensaje
#4 Héctor Miguel
23/05/2007 - 10:59 | Informe spam
hola, Ivan !

__ 1 __
para terminar con este 1er punto... una salida de tema
pues has tocado otra de esas dudas que no se muy bien donde buscar para aclararla.
Se trata de las cadenas de longitud fija y/o variable, y este comentario tuyo:

hay que considerar la memoria que sera 'reservada' y utilizar el tipo de datos mas 'apropiado'



hay alguna forma de declarar una u otra diferenciadamente
o es la propia aplicacion la que discrimina que tipo aplicar en base a las circunstancias? ...



1) haz una prueba +/- como la siguiente:

Sub Variables_String()
Dim Mi_cadena_1 As String * 10, Mi_cadena_2 As String * 10, Mi_cadena_3 As String
Mi_cadena_1 = "a"
Mi_cadena_2 = "aaaaaaaaaaaaaaaaaaaa" ' aqui hay 20 caracteres '
Mi_cadena_3 = "aaaaaaaaaaaaaaaaaaaa" ' aqui hay 20 caracteres '
MsgBox ">" & Mi_cadena_1 & "<" & vbCr & _
">" & Mi_cadena_2 & "<" & vbCr & _
">" & Mi_cadena_3 & "<"
End Sub

el siguiente punto 'pendiente'... [dejame 'masticarlo' mas detenidamente, con un poquitin de mas tiempo] :))

saludos,
hector.

__ 2 __
4) [probablemente] te resultara de mayor 'rapidez' usar los filtros avanzados [copiando a otro lugar]



en realidad era lo que estaba haciendo (sobre todo para practicar con los filtros avanzados, ahora que he 'empezado' a comprenderlos)
pero te explico un poco los detalles del archivo: se trata de una lista de tres columnas
(A -> Codigo ->+o- asi: 100004628 /// B -> Texto -> aaaaaaa /// C -> Costo -> 6,50 )

en la 1ª columna puede haber codigos repetidos y se trataria de concatenar en la 2ª columna de un solo registro
todas las entradas de esa 2ª columna (b) para los registros con el mismo codigo
(en b el texto no es igual aunque coincida el codigo, o al menos puede no serlo)

al final, tras unos cuantos codigos que mas o menos funcionaban el mas rapido de momento es este (para 14000 registros)
por si vieras una forma de hacerlo mas rapido (tarda entre 5 y 9 segundos
no se muy bien porque tanta diferencia siendo el mismo codigo y las mismas (+o-) condiciones)

Sub Rellena_cuentas_6()
Dim ultF As Integer, hj As String, hj2 As String, celdaV As Range, _
ini As Integer, fin As Integer, n As Integer, f As Long, tiempo
tiempo = Timer * 1000
hj = ActiveSheet.Name: ini = 0: fin = 0
Application.ScreenUpdating = False
With ThisWorkbook
.Worksheets.Add after:=.Worksheets(.Worksheets.Count)
hj2 = ActiveSheet.Name: Range("a1:c1") = Array("Codigo", "'Texto", "Costo")
.Worksheets.Add after:=.Worksheets(.Worksheets.Count)
.Worksheets(hj).[a:c].Copy [a1]: hj = ActiveSheet.Name
End With
ultF = [a65536].End(xlUp).Row
Range("a1:c" & ultF).Sort key1:=[a2], order1:=xlAscending, header:=xlYes
With Range("a1:a" & ultF)
.AdvancedFilter xlFilterInPlace, , , True
With .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
For n = 1 To .Areas.Count
With .Areas(n)
Set celdaV = .Cells(.Rows.Count, 1)
End With
If celdaV.Row = ultF Then Exit For
ini = celdaV.Row + 1
If n < .Areas.Count Then fin = .Areas(n + 1).Cells(1, 1).Row - 1 Else fin = ultF
For f = ini To fin
celdaV.Offset(, 1) = celdaV.Offset(, 1) & " " & Range("b" & f)
Next
Set celdaV = Nothing
Next
.EntireRow.Copy Worksheets(hj2).[a2]
End With
End With
Worksheets(hj2).Columns.AutoFit
Application.DisplayAlerts = False
Worksheets(hj).Delete
Application.DisplayAlerts = True
tiempo = (Timer * 1000) - tiempo
MsgBox tiempo
End Sub
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida