Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Eliminar filas escogidas en un combobox

525 views
Skip to first unread message

GRIEGO59

unread,
Oct 13, 2008, 7:21:00 PM10/13/08
to
Hola!

En un formulario tengo un combobox llamado Productos que selecciona
productos de una hoja llamada FichaTécnica.

A medida que se seleccionan los productos en el combobox, los productos van
apareciendo secuencialmente en siete textbox llamados textbox1, textbox2 ...
textbox7.

Es posible que al presionar un botón llamado guardar, se eliminen de la hoja
FhichaTécnica, la(s) fila(s) seleccionadas en el combobox Productos?

La hoja FichaTécnica tiene las siguientes columnas:
Código, Descripción, Color, Ubicación.
La primera fila es de títulos.
Los códigos (productos) pueden repetirse en la hoja FichaTécnica y no están
en orden correlativo.

El código del combobox Productos es:

Private Sub Productos_Change()
dim n as integer
for n = 1 to 7
if me.controls("TextBox" & n).Text = "" then _
me.controls("TextBox" & n).Text = Productos.Value: Exit for
next
End Sub

La cantidad de productos a seleccionar con el combobox depende del estado de
ánimo del cliente que compra los productos, pero nunca será mayor de siete.

Si el cliente que compra los productos cambia de opinión antes de presionar
el botón Guardar, puede hacer modificaciones a su pedido antes de presionar
el botón guardar

Uso Excel 2003.

Gracias por su ayuda,
Darío.

Ivan

unread,
Oct 13, 2008, 9:09:49 PM10/13/08
to
hola Dario,


> ...al presionar un botón llamado guardar, se eliminen de la hoja


> FhichaTécnica, la(s) fila(s) seleccionadas en el combobox Productos?

> La primera fila es de títulos.


> Los códigos (productos) pueden repetirse en la hoja FichaTécnica y no están
> en orden correlativo.

=>como requisito previo =>

.-> suponiendo que cargas el combo con 'List' y con todos los
registros de la hoja [como creo recordar del otro hilo],

.-> y que no realizas modificaciones en el orden y/o cantidad de
elementos de la hoja entre la ultima carga del combo y la pulsacion
del boton

a) si 'solo' quisieses eliminar la fila del producto seleccionado en
el combo te bastaria con algo tipo =>

worksheets("FichaTécnica").rows(tuCombobox.listindex + 2).delete

b) pero como incluyes un/os plural/es, y dado que, si no recuerdo mal,
los combobox de vba no tienen la propiedad multiselect, unido a que
comentas que los codigos pueden estar duplicados en la hoja, creo que
=>

una posible solucion seria cargar en algun sitio el nº de fila de cada
elemento segun cargues cada textbox (pej. en el Tag de cada textbox, o
en una matriz, o en ...) y recorrelo con un bucle al pulsar el boton,
eliminando las filas correspondientes.

aunque OJO, como los textbox no tendrian que cargarse necesariamente
en un orden 'creciente' (en lo que a nº de fila se refiere), antes de
proceder a la eliminacion deberias asegurarte de que esta se hace en
orden inverso, es decir del nº de fila mas alto al mas bajo, para lo
que deberias usar alguna forma de ordenacion previa o durante el bucle

pej., suponiendo que has ido cargando en el tag de cada textbox
el .listindex del combo con cada producto cargado, pej. con algo
parecido a esto dentro del mismo bucle que carga los textbox =>

Me.Controls("TextBox" & n).Tag = ComboBox1.ListIndex

puedes poner esto en el boton (pero OJO, deberias borrar los textbox,
o al menos el tag, cada vez que elimines las filas (tambien deberias
actualizar el combo))

Private Sub CommandButton1_Click()
Dim f As Long, max As Long, cont As Byte, n As Byte
max = ComboBox1.ListCount
cont = 0
Do
f = -1
For n = 1 To 7
With Me.Controls("TextBox" & n)
If .Tag > f And .Tag < max Then _
f = .Tag
End With
Next
If f > -1 Then Worksheets("FichaTécnica").Rows(f + 2).Delete
max = f
Loop Until max = -1
borrarTxts
cargarCombo ComboBox1, "FichaTécnica"
End Sub

' Para borrar los textbox
'
Sub borrarTxts()
Dim n As Byte
For n = 1 To 7
With Me.Controls("TextBox" & n)
.Text = ""
.Tag = ""
End With
Next
End Sub

' Para volver a cargar el combo
'
Sub cargarCombo(ByRef combo As ComboBox, ByVal hj As String)
Dim rng As Range
Set rng = Worksheets(hj).[a1].CurrentRegion
With combo
.Clear
.List = rng.Offset(1).Resize(rng.Rows.Count - 1, _
rng.Columns.Count).Value
End With
Set rng = Nothing
End Sub

OJO: en los ej. el combo se llama CombBox1

puedes inhabilitar el refresco de pantella (application.screenUpdating
= false) al principio del procedimiento del boton y habilitarlo al
final, aunque con 7 filas solo tampoco creo que se note mucho

lo dicho, solo alguna posibilidad

espero te ayude

Un saludo
Ivan

Ivan

unread,
Oct 13, 2008, 9:29:24 PM10/13/08
to
hola de nuevo,

cambia el codigo del boton y de cargar el combo por estos otros =>

' en este, aunque el de antes funcionaba igual, se habia
' quedado algo de chatarra, aparte de un par de detalles
' que ahora [a mi] me gustan mas
'
Private Sub CommandButton1_Click()
Dim f As Long, max As Long, n As Byte
max = ComboBox1.ListCount


Do
f = -1
For n = 1 To 7
With Me.Controls("TextBox" & n)
If .Tag > f And .Tag < max Then _
f = .Tag
End With
Next

If f = -1 Then Exit Do
Worksheets(nombreHoja).Rows(f + 2).Delete
max = f
Loop
borrarTxts
cargarCombo ComboBox1, nombreHoja
End Sub

' en este se previene que no queden mas filas en la hoja


'
Sub cargarCombo(ByRef combo As ComboBox, ByVal hj As String)
Dim rng As Range
Set rng = Worksheets(hj).[a1].CurrentRegion
With combo
.Clear

If rng.Rows.Count > 1 Then _


.List = rng.Offset(1).Resize(rng.Rows.Count - 1, _
rng.Columns.Count).Value
End With
Set rng = Nothing
End Sub

un saludo
Ivan

GRIEGO59

unread,
Oct 14, 2008, 12:33:01 AM10/14/08
to
Hola, Ivan!
Me dió:
Error de compilación
y marca el código:
borrarTxts

Por cierto el código para volver a cargar el combobox? supongo que debo
dejar mi código para cargar el combobox, es decir no eliminar mi código
UserForm nitialize()
... Yo entiendo que tu código es para cargar el combobox cada vez que haga
click.

Gracias por tu ayuda!

Darío


"Ivan" escribió:

GRIEGO59

unread,
Oct 14, 2008, 12:35:01 AM10/14/08
to
Hola otra vez,
No sería másfácil vincular siete celdas de una hoja de cálculo con los siete
textbox indicándole que para cada cambio en los texbox inserte el número de
línea del combobox? y luego ordenar las celdas y luego eliminar las filas de
mayor a menor?

Darío

"Ivan" escribió:

Ivan

unread,
Oct 14, 2008, 11:30:29 AM10/14/08
to
hola Dario, te contesto por aqui a los dos mensajes. Lo 1º el ultimo=>

> No sería másfácil vincular siete celdas de una hoja de cálculo con los siete
> textbox indicándole que para cada cambio en los texbox inserte el número de
> línea del combobox? y luego ordenar las celdas y luego eliminar las filas de
> mayor a menor?

es una posibilidad, pero con algun que otro condicionante. Pej: =>

.-> tendrias que:

a) o bien usar una hoja diferente,
b) o usar un rango de celdas 'por debajo' de tu lista,
c) o eliminar solo las celdas de la fila que te interesen [no la fila
entera]
d) o usar cualquier otra forma de evitar 'superposicion' de rangos/
filas

de no ser asi, corres el riesgo de que una de las filas eliminadas
incluya alguna de las celdas vinculadas, con lo que podria suceder que
la fila incluida en dicha celda no se eliminase

por otro lado, y salvo que quieras darle un uso diferente al Tag de
los textbox, no tengo muy claro que fuese mas 'eficiente'. Incluso con
el uso de este (y salvo que usases una hoja aparte), te evitas riesgos/
tareas innecesarios en el caso de que la hoja contenga algun otro tipo
de elementos, tipo formulas, formatos, etc

. Aunque en cualquiera de los casos, para ese volumen de trabajo (7
texts, 7 filas, 7 etc...) no creo que la diferencia sea muy apreciable


en cuanto al otro mensaje =>

>Hola, Ivan!
>Me dió:
>Error de compilación
>y marca el código:
>borrarTxts


a mi me funciona perfectamente =>

.-> asegurate de que estas copiando todos los elementos exactamente
como estan en el mensaje, y cambia solo lo que pueda referirse a
nombre de la hoja, del combo, etc.

.-> asegurate tambien de que no hay procedimientos REPETIDOS. Es
decir, no puede haber 2 procedimientos llamados igual

.-> aunque si lo copias tal cual esta en un nuevo formulario con el
modulo en blanco (y claro, una vez insertados los controles >textBox1,
2, .., 7, ComboBox1 y CommandButton1>) no deberia darte problemas,
echale un ojo a lo que te comentaba en el otro hilo sobre los
procedimientos y las instrucciones en un modulo

.-> revisa los codigo e intenta analizarlos con la ayuda de F1 <que
ayuda mas de lo que parece>


>Por cierto el código para volver a cargar el combobox? supongo que debo
>dejar mi código para cargar el combobox, es decir no eliminar mi código
>UserForm nitialize()
>... Yo entiendo que tu código es para cargar el combobox cada vez que haga
>click.

[te comento mi parecer, aunque, por lo que despues te comento, en este
caso no haria falta 'recargar' el combo, es tan solo una forma entre
otras,]

.-> en realidad dicho codigo lo podrias usar tambien para la carga
inicial, Y en todas y cada una de las ocasiones en que A TI te
interese actualizar el contenido del combo

.-> lo que debes de tener claro es que lo que llamas 'tu codigo
UserForm nitialize() ', no tiene nada que ver con la carga del combo
en si mismo.

dicho 'Procedimiento' es un tipo de procedimiento de los admitidos por
VBa, que a grosso modo podriamos resumir en tres tipos: procedimientos
Sub, procedimientos Function y procedimientos Property

.-> un tipo de procedimiento especial [aunque reamente sean Sub]
serian los procedimientos de evento, que por decirlo en plan simple,
son procedimientos que se 'disparan/ejecutan' como reaccion a alguna
accion sobre un objeto. Estas acciones pueden ser de varios tipos,
pero para no liarte dejemoslo en las mas evidentes:=>

.-> hacer click sobre un form/control (dispara el evento Click de
dicho control),
,-> pulsar una tecla cuando un form/control tiene el foco dispara una
sucesion de eventos para dicho control >KeyDown, KeyPress, KeyUp ...<
.-> cambia el contenido de una celda de una hoja de calculo dispara el
evento Change de esa hoja de calculo
.-> cambiar el contenido de un textbox dispara el evento Change del
textbox
.-> cargar un Userform en memoria (es decir, crearlo y/o mostrarlo por
1ª vez) dispara, entre otros el evento Initialice

bueno, hay muchos mas, y en generl conviene tener lo mas claro posible
cuando y en que orden se disparan antes de utilizarlos, si no que
remos llevarnos mas de una sorpresa (usa lo mas que puedas F1).

Todos estos ejemplos vienen predefinidos por la aplicacion, es decir,
tu no tienes que crearlo, sencillamente te limitas a utilizar el que
mas te interese para realizar una accion aprovechando que sabes en que
momento se ha de disparar determinado evento. (NOTA: tambien podemos
crear nuestros propios eventos, pero esa es otra historia])

en tu caso estas aprovechando el evento Initialice del formulario,
para, entre otras cosas, cargar el contenido del combo al crear el
formulario. [dicho evento es uno de los varios que dicho objeto
'Expone']

en este caso podrias sustituir el 'FRAGMENTO' de codigo con el que
cargas el combo por el uso del procedimiento 'cargarCombo', que al fin
y al cabo hace exactamente lo mismo pero usando un mismo procedimiento
cada vez que quieras volver a cargar el combo, en lugar de tener que
repetir un codigo basicamente identico cada vez que quieras hacerlo
(recuerda que en este caso el procedimiento lleva dos parametros a los
que le tienes que pasar como argumentos el propio combo y el nombre de
la hoja)

pero ten en cuenta que, tanto si usas dicho procedimiento, como si
usas el codigo que tenias, este debe de ir 'DENTRO' de alguno de los
tipos de procedimientos comentados (en el caso de 'cargarCombo', lo
que haces es solamente LLAMARLO desde dentro de ese otro procedimiento
<Initialice en este caso>), y en si mismos no lo sustituyen, sino que
las acciones que conlleva se ejecutaran cuando se ejecute dicho
procedimiento.

bueno, lo mismo te he hecho la picha un lio, que se dice por aqui,
pero para que al menos te suene. Lo suyo es seguir insistiendo y
practicando. Y recurrir sin miedo a F1. Al final se acaba entendiendo
y haciendose imprescindible

un saludo
Ivan

Ivan

unread,
Oct 14, 2008, 11:43:52 AM10/14/08
to
hola de nuevo (jod..., no hay manera, no se como lo hago, pero al
final siempre acabo mandando tropecientos mensajes. ...Sorry)

al final, con tanto rollo se me ha olvidado esto =>

> [..., en este caso no haria falta 'recargar' el combo, es tan solo una forma entre
> otras,]

me referia a que realmente, en este caso, no hace falta recargar el
combo porque te basta ria usar el metodo 'RemoveItem' del combobox
para eliminar dicha entrada del combo a la vez que eliminas la fila de
la hoja, es decir algo asi=>


Private Sub CommandButton1_Click()
Dim f As Long, max As Long, n As Byte
max = ComboBox1.ListCount
Do
f = -1
For n = 1 To 7
With Me.Controls("TextBox" & n)
If .Tag > f And .Tag < max Then _
f = .Tag
End With
Next
If f = -1 Then Exit Do
Worksheets(nombreHoja).Rows(f + 2).Delete

' aqui eliminamos la fila del combo
Combobox1.removeItem(f)
'

max = f
Loop
borrarTxts
cargarCombo ComboBox1, nombreHoja
End Sub

es otra posibilidad

un saludo
Ivan

GRIEGO59

unread,
Oct 14, 2008, 3:52:01 PM10/14/08
to
Hola, Ivan!

Mas o menos he entendido como un 5% de lo que me has explicado.
Realmente no es "Mi código" me lo han enseñado en este foro y lo uso como mío.

Al usar F1 sobre el código "borrarTxts" me dice:

"...Palabra clave no encontrada.
Puede que se haya pedido ayuda para una palabra clave no válida de Visual
Basic"

"...Puede estar incluida en una biblioteca de objetas que no está incluida
en las referencias"

Al presionar el botón guardar me dice:

"Error de Compilación:
No se ha definido Sub o Fuction"
y marca esa palabrita "borrarTxts"

He borrado todos los códigos del formulario y he dejado solamente mi
Initialize y tus códigos.

Por cierto, en tu código donde aparece:
Then _
y
- 1 , _

He escrito:
Then(espacio)_(enter)
y
- 1 ,(espacio)_(enter)

No sé si esto es la causa del error.
Estoy copiando tus códigos manualmente, no puedo usar la opción de copiar.
Pero he tenido cuidado de copiar correctamente y me he asistido por las
palabritas que van saliendo automáticamente a medida que uno va escribiendo.

Gracias apor tu ayuda,

Darío.

Ivan

unread,
Oct 14, 2008, 6:03:48 PM10/14/08
to
hola Dario,

> Mas o menos he entendido como un 5% de lo que me has explicado.

me temo que la 'capacidad didactica' es una mas de mis carencias.
Unido a mi 'verborrea', no me extraña que no hayas entendido de la
misa la media.

de todas formas, antes de 'intentar volver a entrar en materia',
permiteme un comentario, y espero que no te moleste y lo tomes solo
como la exposicion de algo que yo haria de estar en tu caso (de hecho
es mas o menos lo que hice en su dia):

si no recuerdo mal, creo que llevas bastante tiempo trasteando con VBA
excel, o al menos creo recordar mensajes tuyos en el foro hace ya
bastantes meses.

de ello deduzco, que +/- te atrae esto de la programacion con macros
(o como poco que te es bastante necesario)

si es asi, yo en tu caso haria (hice) un parentesis para intentar
estudiar al menos las generalidades del lenguaje de programacion con
el que quieres trabajar. Ello te permitiria, con muy poco esfuerzo,
multiplicar exponencialmente los frutos obtenidos con tu trabajo.

no me refiero a profundizar, sino a intentar comprender lo mas basico
para poco a poco ir añadiendo/descubriendo nuevas cosas

Y realmente para ello no creo que necesites mas alla de una o dos
tardes.

Se trataria tan solo de intentar conocer cosas como estas:

a) Tipo, declaracion, usos y alcance de procedimientos
b) Tipo, declaracion, usos y alcance de variables y constantes
c) Estructuras de decision
d) Operadores
c) y un sinfin ....:-D

es decir la estructura basica del lenguaje.

En general la mayor parte podras encontrarlo en la propia ayuda, pero
ademas la web esta llena de informacion, que deberas ir discerniendo
como tu creas/quieras/puedas

bueno, disculpa la charla. En realidad es una descripcion de lo que yo
hice (y sigo haciendo)

y volviendo al hilo =>

> Al presionar el botón guardar me dice:
>
> "Error de Compilación:
> No se ha definido Sub o Fuction"
> y marca esa palabrita "borrarTxts"
>
> He borrado todos los códigos del formulario y he dejado solamente mi
> Initialize y tus códigos.

¿que codigos has dejado?¿ has incluido el procedimiento 'borrarTxts'
incluido en mi 1er mensaje?

es decir, un procedimiento es un bloque de codigo que comienza por una
de estos 3 terminos: 'Sub', 'Function' o 'Property' [aunque puede y
suele ir precedido de un modificador de alcance ( Private, Public, y
alguno mas) y termina con un 'End Sub', 'End Function' o 'End
Property'

en este caso el procedimiento 'borrarTxts' es este que te ponia en el
1er mensaje =>

' Para borrar los textbox
'
Sub borrarTxts()
Dim n As Byte

For n = 1 To 7
With Me.Controls("TextBox" & n)

.Text = ""
.Tag = ""
End With
Next
End Sub

a este procedimiento se le puede llamar desde otros procedimientos
cuando nos interese. En este caso se le llama desde el evento Click
del boton guardar, despues de haber eliminado las filas =>

Private Sub CommandButton1_Click()
Dim f As Long, max As Long, n As Byte
max = ComboBox1.ListCount

' co estos dos bucles vamos obteniendo el nº
' de fila de mayor a menor
'


Do
f = -1
For n = 1 To 7
With Me.Controls("TextBox" & n)
If .Tag > f And .Tag < max Then _
f = .Tag
End With
Next
If f = -1 Then Exit Do

' aqui eliminamos la fila en la hoja
'
Worksheets(nombreHoja).Rows(f + 2).Delete

' aqui eliminamos la fila del combo
'
Combobox1.removeItem(f)

'
max = f
Loop

' una vez eliminadas las filas, llamamos al procedimiento
' que borra los textbox =>
'
borrarTxts

End Sub

NOTA: tambien podrias usar la instruccion Call =>

Private Sub CommandButton1_Click()
'
'.......aqui iria el mismo codigo que en el otro
'......
' una vez eliminadas las filas, llamamos al procedimiento
' que borra los textbox =>
'
Call borrarTxts ()

End Sub

si te fijas aqui he eliminado la LLAMADA al procedimiento
'cargarCombo' porque al usar 'RemoveItem' ya no es necesario, pues
eliminamos la fila del combo a la par que la de la hoja

pero si quisieras utilizar dicho procedimiento pra cargar el combo,
bien en el evento 'Initialice' del formulario, bien en cualquier otro
procedimiento del modulo del formulario deberias hacer algo asi =>

este es el PROCEDIMIENTO 'cargarCombo' =>

' Para volver a cargar el combo
'

Sub cargarCombo(ByRef combo As ComboBox, ByVal hj As String)
Dim rng As Range
Set rng = Worksheets(hj).[a1].CurrentRegion
With combo
.Clear

.List = rng.Offset(1).Resize(rng.Rows.Count - 1, _
rng.Columns.Count).Value
End With
Set rng = Nothing
End Sub

como ves comienza por 'Sub' seguido por el nombre del procedimiento (y
los parametros si los tiene), y se cierra con 'End Sub'

y para llamarlo [usarlo] pej. en el evento 'Initialice' que exponias
en el otro hilo, seria algo asi =>

Private Sub UserForm_Initialize()
Productos.ColumnCount = 4
Productos.ColumnWidths = "45;180;100,25"
cargarCombo Productos, "FichaTécnica"
End Sub

o para que lo veas un poco mas claro, usando Call directamente (en
este caso deberas incluir los argumentos entre parentesis)

Private Sub UserForm_Initialize()
Productos.ColumnCount = 4
Productos.ColumnWidths = "45;180;100,25"

Call cargarCombo(Productos, "FichaTécnica")

End Sub

>
> Por cierto, en tu código donde aparece:
> Then _
> y
> - 1 , _
>
> He escrito:
> Then(espacio)_(enter)
> y
> - 1 ,(espacio)_(enter)

la verdad es que no me acabo de enterar de lo que has hecho, pero te
comento que el guion bajo al final de una linea (precedido de un
espacio) es el caracter de continuacion de linea, es decir que la
instruccion continua en el siguiente renglon.

en realidad es mas o menos igual que cuando cortamos una palabra al
escribrir, lo unico que lo que cortamos no es una palabra sini una
instruccion y el guion hay que precederlo de un espacio

su uso es sobre todo visual, para poder ver las instrucciones
completas cuando estas se alargan sin tener que usar el scroll

bueno, supongo que habre vuelto a liarte, pero si realmente estas
revisando 'palabra' por 'palabra' (e incluso letra por letra) que la
transcripcion esta bien, deberia funcionarte

un saludo
Ivan.

GRIEGO59

unread,
Oct 16, 2008, 9:00:00 PM10/16/08
to
Hola, Ivan!
Gracias por la ayuda y las recomendaciones!
Esto se me ha hecho dificil.
Voy a tomar unas horas de vacaciones.

Saludos,

Darío.

"Ivan" escribió:

0 new messages