Mensajes recientes

Páginas: [1] 2 3 ... 10
1
Varias / Obtener lista de controles seleccionados
« Último mensaje por xavi en Octubre 19, 2021, 12:06:16 pm »
Palabras clave: diseño, controles, selección, lista
Autor: Visto a ADezii en BYTES.COM

Objetivo:
Mihura pregunta si es posible obtener la lista de controles seleccionados en un formulario en vista diseño. ¿El motivo? la vagancia de escribir los nombres de los controles.

Respuesta
Una búsqueda en Google nos posiciona a Chema y un servidor en la misma página. Ahí descubrimos la propiedad InSelection y un código para determinar si está seleccionado.

Código: [Seleccionar]
? IsControlSelected (Forms!Customers, "CompanyName")
 
Function IsControlSelected(frm As Form, strControlName As String) As Boolean
 Dim intI As Integer, ctl As Control
 If frm.CurrentView <> 0 Then
   ' Form is not in Design view.
   Exit Function
 Else
   For intI = 0 To frm.Count - 1
     Set ctl = frm(intI)
     If ctl.InSelection = True Then
       ' Is desired control selected?
       If UCase(ctl.Name) = UCase(strControlName) Then
         IsControlSelected = True
         Exit Function
       End If
     Else
       IsControlSelected = False
     End If
   Next intI
 End If
End Function

Al final la cosa es más simplificable, tal como nos enseña Mihura.

Código: [Seleccionar]
Function ControlesSeleccionados(frm As Form) As String
    Dim strTmp As String
    Dim ctl As Control
   
    For Each ctl In frm.Controls
        If ctl.InSelection Then
            strTmp = strTmp & ", " & Chr(34) & ctl.Name & Chr(34)
        End If
    Next ctl
    ControlesSeleccionados = Trim(Mid(strTmp, 2))
End Function
2
Varias / Copiar al portapapeles
« Último mensaje por xavi en Septiembre 24, 2021, 10:19:31 am »
Palabras clave: copiar, portapapeles, clipboard
Autor: Mihura

Objetivo:
McPegasus pregunta en un grupo si existen alternativas al SendKeys ( ;D ) para copiar un texto dado en el portapapeles. Apunta 2 soluciones: una mediante API y otra mediante MSForms.DataObject.
Parece ser que la API está fallando últimamente y que la MSForms obliga a tener la referencia (cosa no siempre posible/deseable)

Respuesta
Mihura, casi al límite del tiempo que había marcado, nos obsequia con esta pequeña maravilla de 5 líneas:

Código: [Seleccionar]
Public Function RT_CopyToClip(ByVal Expresion As String)
    Const DATAOBJECT_BINDING As String = "new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}"
    With CreateObject(DATAOBJECT_BINDING)
        .SetText Expresion
        .PutInClipboard
    End With
End Function
3
Consultas / Saber los registros afectados por una consulta de acción
« Último mensaje por xavi en Septiembre 20, 2021, 06:19:57 pm »
Palabras clave: consulta, SQL, acción, registros
Extraído de: Ayuda de Access

Situación
Lanzamos una consulta de acción que impactará sobre una cantidad de registros. A priori la única forma de saberlo sería abrir un recordset con los mismos criterios y contar los registros impactados. (bueno, eso no siempre sería cierto pero no entraremos en detalles).
Lo que deseamos es, una vez lanzada la consulta, saber cuantos registros se han visto afectados.

Ejemplo: deseamos actualizar todos los registros que contengan el valor "A" en un campo llamado "Zona". Actualizaremos el campo Comercial de esos registros al valor "Xavi".

Respuesta
Utilizaremos la propiedad RecordsAffected del objeto Database de DAO que devuelve la cantidad de registros que se modificaron mediante la ultima llamada del método Execute de un objeto DAO.Database

Para ello es necesario que declaremos un objeto DAO.Database y lo utilizemos para lanzar el Execute (no nos vale DoCmd.RunSQL)


Código: [Seleccionar]
    Dim dbs As DAO.Database
    Set dbs = CurrentDb
   
    dbs.Execute "UPDATE Clientes SET Comercial = 'Xavi' WHERE Zona = 'A'", dbFailOnError
    MsgBox "Actualización de datos realizada. Registros afectados: " & dbs.RecordsAffected, vbInformation
    dbs.Close
    Set dbs = Nothing
4
Consultas / Construir cadenas SQL con referencias
« Último mensaje por xavi en Abril 28, 2021, 12:04:25 am »
Palabras clave: consulta, SQL, referencias, controles
Extraído de: De aquí y de allí

Pregunta
¿Cuál es la forma de construir cadenas con criterios de diferentes tipos de datos?

Respuesta
Cuando se construyen cadenas SQL en un formulario es necesario tener presente que:
- Las referencias a valores que se encuentran en controles del formulario dónde se ejecuta el código (ME!...) deben "extraerse" de la cadena
- El tipo de valor que contiene el campo es relevante para delimitar y formatear los datos.
 + los textos se delimitan con comillas... pero dado que las comillas ya están delimitando la propia SQL, lo sustituimos por apóstrofes.
 + los números enteros no se delimitan y no dan ningún problema
 + los números decimales, al utilizar la coma, pueden dar problemas. Por ese motivo podemos utilizar Str
 + las fechas se delimitan con # y se "americanizan"

"SELECT * FROM UnaTabla WHERE UnCampoTexto = '" & Me!UnCampoTexto & "' AND UnCampoEntero = " & Me!UnCampoEntero & " AND UnCampoDecimal = " & Str(Me!UnCampoDecimal) & " AND UnCampoFecha = #" & Format(Me!UnCampoFecha, "mm/dd/yyyy") & "#"
5
Varias / Especificación importación de Texto/CSV dónde títulos no es primera línea
« Último mensaje por xavi en Marzo 15, 2021, 10:42:45 am »
Palabras clave: recordset, fichero, archivo, texto, plano, CSV
Autor: raipon

Objetivo:
A raíz de la necesidad de importar datos de un fichero CSV dónde la primera fila está llena de porquería, la segunda contiene los nombres de campos y solo a partir de la tercera aparecen datos, raipon nos enseñó como manejar esa casuística:

La clave es el el campo StartRow de la especificación de importación. No es un campo que aparezca en el asistente de importación/vinculación por lo que será un poco complicado crear la especificación.

El truco es:
1. Hacer una copia del fichero
2. Editarlo para dejar la primera fila como la de los títulos
3. Hacer una importación con asistente guardando la especificación
4. Modificar la especificación en la tabla MSysIMEXSpecs (tabla de sistema; podría estar oculta)
5. Eliminar la copia de test y probar con ficheros reales


6
Módulos / Re:Averiguar si existe un procedimiento
« Último mensaje por xavi en Febrero 22, 2021, 12:24:01 pm »
Como siempre, sólo hay que bucear un poco para encontrar una respuesta que mejore ampliamente el rendimiento. Y, como no, la respuesta es de Happy. Utilizando el objeto indocumentado WizHook.

Código: [Seleccionar]
Function whExisteProcedimiento(strProcedure As String) As Boolean
    WizHook.Key = 51488399
    whExisteProcedimiento = WizHook.GlobalProcExists(strProcedure)
End Function
7
Formularios / Desplegar selector de fecha
« Último mensaje por xavi en Enero 23, 2021, 10:05:11 pm »
Palabras clave: fecha, desplegar, datapicker, selector
Autor: Missinglinq
Extraído de: Access Forums

Pregunta
¿Cómo puedo desplegar automáticamente el selector de fecha al entrar en un cuadro de texto?

Respuesta
En el evento al recibir enfoque (GotFocus) desplegamos el selector. En el evento Al cambiar, mandamos el foco a otro control

Código: [Seleccionar]
Private Sub DateField_GotFocus()
  DoCmd.RunCommand acCmdShowDatePicker
End Sub

Private Sub DateField_Change()
  Me.AnotherControl.SetFocus
End Sub

Private Sub DateField_AfterUpdate()
  'AfterUpdate code goes here
End Sub

Si el cuadro de texto fuera el primer control del formulario podríamos simular el proceso con el evento Timer

Código: [Seleccionar]
Private Sub Form_Load()
  Me.TimerInterval = 1
End Sub

Private Sub Form_Timer()
  Me.TimerInterval = 0
  Me.DateField.SetFocus
  DoCmd.RunCommand acCmdShowDatePicker
End Sub
8
API / Nombre corto, nombre largo
« Último mensaje por xavi en Enero 18, 2021, 07:37:20 pm »
Palabras clave: carpeta, directorio, fichero, archivo, nombre, corto, largo API
Autor: Happy
Extraído de: Access y VBA

Objetivo:
Rescato estos procedimientos de Happy para obtener el nombre corto de fichero a partir del nombre largo y viceversa.


En un módulo independiente:
Código: [Seleccionar]
Option Compare Database
Option Explicit

Private Declare Function GetLongPathName Lib "kernel32" _
                Alias "GetLongPathNameA" _
                (ByVal lpszShortPath As String, _
                ByVal lpszLongPath As String, _
                ByVal cchBuffer As Long) As Long

Private Declare Function GetShortPathName Lib "kernel32" _
                Alias "GetShortPathNameA" _
                (ByVal lpszLongPath As String, _
                ByVal lpszShortPath As String, _
                ByVal lBuffer As Long) As Long

Function GetLongName(ShortPath As String) As String
Dim LenLongName As Long
Dim buffer As String * 1000

    LenLongName = GetLongPathName(ShortPath, _
                          buffer, Len(buffer))
    If LenLongName Then
        GetLongName = Left$(buffer, LenLongName)
    End If

End Function

Function GetShortName(LongPath As String) As String
Dim LenShortName As Long
Dim buffer As String * 1000

    LenShortName = GetShortPathName(LongPath, _
                          buffer, Len(LongPath))
    If LenShortName Then
        GetShortName = Left$(buffer, LenShortName)
    End If

End Function

9
Varias / Obtener lenguaje de Office
« Último mensaje por xavi en Enero 08, 2021, 12:56:12 pm »
Palabras clave: lenguaje, idioma
Autor: xavi
Extraído de: Web de Microsoft

Por necesidades del parámetro Format de la función PasteSpecial de Excel, me he visto forzado a buscar si existía una forma de averiguar el idioma de Excel. Y me he topado con esto:

Código: [Seleccionar]
Application.LanguageSettings.LanguageID(msoLanguageIDUI)


El valor que devuelve es un numérico.

URL's dónde obtener valores y códigos
MsoLanguageID (enumeración) (Office)
Identificadores de idioma y valores de identificador de OptionState en Office 2016

10
Excel / Última fila con datos de un fichero Excel
« Último mensaje por xavi en Octubre 22, 2020, 06:51:09 pm »
Palabras clave: Excel, automatización, registros
Autor: Jesus Mansilla (Mihura)

En ocasiones necesitamos leer un fichero Excel mediante automatización y, para poder mostrar "algo" que nos de idea del progreso, es necesario averiguar la cantidad de registros afectados,

Una opción es insertar una fórmula en una celda "lejana" que nos haga un COUNTA (CONTARA) de los registros de una columna que sepamos debe estar toda rellena.

xls.ActiveSheet.Cells(1, 255).FormulaR1C1 = "=COUNTA(C1)

Leer el resultado (restarle 1 si existe una fila de titulos) y eliminar el contenido de la celda. Hay que acordarse de que, al cerrar el Excel, no se guarden los cambios.

Jesus presenta una alternativa:

UltimaFila = xls.ActiveSheet.Cells(xls.ActiveSheet.Rows.Count, 1).End(xlUp).Row

Traducido: posicionarse en la ultima fila de la hoja (ActiveSheet.Rows.Count) en su primera columna (1) y "tirar p'arriba" con .End(xlUp)  (equivalente a Ctrl + flecha arriba). Ello posiciona en la ultima celda escrita de la columna. Y de allí tomamos la fila (.Row)

Lo mismo para las columnas
UltimaColumna = xls.ActiveSheet.Cells(1, xls.ActiveSheet.Columns.Count).End(xlToLeft).Column

Ingenioso.
Páginas: [1] 2 3 ... 10