Archivo de la categoría: SomeCode

Saber de los procesos que se estan ejecutando… Ordenadamente

Efectivamente… para responder a la pregunta de si podemos ordenar la consulta, añadiremos simplemente el ‘Order By’ antes del select, tal y como sigue :

         (From procesos In ProcesosLocales _
          Order By procesos.Id _
          Select _
          New MiProcessInfo() With {.Id = procesos.Id, _
                                    .Nombre = procesos.ProcessName} _
         ).ToList
        ‘ En este caso obtenemos la lista ordenada por el Id

         (From procesos In ProcesosLocales _
          Order By procesos.ProcessName _
          Select _
          New MiProcessInfo() With {.Id = procesos.Id, _
                                    .Nombre = procesos.ProcessName} _
         ).ToList
        ‘ En este caso obtenemos la lista ordenada por el Nombre


No olvideis que se puede ordenar de mayor a menor o Viceversa usando la opcion ‘Ascending‘ o ‘Descending‘ justo despues del nombre del campo a ordenar.

Saludos,
Pep Lluis,

PD. la ‘V’ de Vice por gentileza de Fran… jajajajaja.

 

Combinar un ComboBox y un TextBox con diferentes columnas de una BD

A peticion de Ariel, me complace compartir este sencillo ejemplo de cómo enlazar el Combobox visualizando el valor de una columna asignando el conocido ‘DisplayMember’ y obteniendo el valor de otra columna con su ‘ValueMember’. De esa forma entre otras muchas aplicaciones, lo tendremos disponible y podremos visualizarlo en un textbox por poner un ejemplo.

 

Public Class Form1
    Private MiComboBox As New ComboBox
    Private MiTextBox As New TextBox

    Private Sub Form1_Load(… ..) Handles MyBase.Load
       
        ‘ Simular tabla Maestros
       
        Dim Maestros As New DataTable(«Maestro»)
        Maestros.Columns.Add(«Nombre»)
        Maestros.Columns.Add(«Matricula»)
        Maestros.Rows.Add(«Juan Jose», «1001 BCN»)
        Maestros.Rows.Add(«Alberto Juan», «2002 ABC»)
        Maestros.Rows.Add(«Antonio Miguel», «3003 NJR»)
        Maestros.Rows.Add(«Jose Maria», «4004 FCB»)
       
        ‘ Construir el DataSet
       
        Dim MiDataSet As New DataSet
        MiDataSet.Tables.Add(Maestros)
       
        ‘ Añadir un ‘ComboBox’
        ‘ Conteniendo la tabla ‘Maestro’
        ‘ mostrando la columna ‘Nombre’
        ‘ y señalando como valor a la matricula
       
        MiComboBox.DisplayMember = «Nombre»
        MiComboBox.ValueMember = «Matricula»
        MiComboBox.DataSource = MiDataSet.Tables(«Maestro»)
        MiComboBox.Dock = DockStyle.Top
        Me.Controls.Add(MiComboBox)
        AddHandler MiComboBox.SelectedIndexChanged, AddressOf ActualizarTextBox
        MiTextBox.Dock = DockStyle.Bottom
        Me.Controls.Add(MiTextBox)
        ActualizarTextBox()
    End Sub
   
    ‘ Mover el valor seleccionado del combo al textbox
    Private Sub ActualizarTextBox()
        MiTextBox.Text = MiComboBox.SelectedValue
    End Sub
End
Class

Saber de los procesos que se estan ejecutando

»
» Saber de los procesos que se estan ejecutando
»
Public Class Form1

    Private Sub Form1_Load(….) Handles MyBase.Load

        ‘Obtener la lista de procesos en ejecucion
        Dim ProcesosLocales As Process() = Process.GetProcesses
        ‘Construir un DataGridView para visualizar
        Dim MiDgv As New DataGridView
        ‘Acoplarlo al form rellenandolo en su totalidad
        MiDgv.Dock = DockStyle.Fill
        Me.Controls.Add(MiDgv)
        ‘ Podriamos utilizar : MiDgv.DataSource = ProcesosLocales.ToList
        ‘ aunque antes deberiamos contemplar las excepciones 
        ‘ derivadas de la falta de privilegios en el
        ‘ acceso a ciertas propiedades de los procesos
        MiDgv.DataSource = _
         (From procesos In ProcesosLocales Select _
          New MiProcessInfo() With {.Id = procesos.Id, _
                                    .Nombre = procesos.ProcessName} _
         ).ToList
    End Sub
End
Class

Class MiProcessInfo
   
    ‘Leer/Asignar su Id
    Private m_Id As String
    Public Property Id() As Integer
        Get
            Return m_Id
        End Get
        Set(ByVal value As Integer)
            m_Id = value
        End Set
    End Property
   
    ‘Leer/Asignar su Nombre
    Private m_Nombre As String

    Public Property Nombre() As String
        Get
            Return m_Nombre
        End Get
        Set(ByVal value As String)
            m_Nombre = value
        End Set
    End Property
End
Class

Todo lo que quise saber de mi disco y no me atreví a preguntarlo

Tal como os tengo acostumbrados, con el trasfondo de preguntas que se repiten y repiten, os facilito un ejemplo de cómo rastrear toda la información de nuestro disco “lógico” utilizando el conocido “System.Management” del ‘Framework 2.0’.

En el siguiente ejemplo rellenamos un “DomainUpDown” con los nombres de las características de nuestro disco, a continuación rellenamos un ‘label’ con la descripción de la característica cada vez que el “DUD” cambia de indice… sencillo, verdad? Utilizando este método podremos acceder a las propiedades disponibles sin tener que buscar sus nombres de antemano. A pesar de que os anticipo que a menudo muchos de nosotros intentamos obtener información o características que no están disponibles para ese “disco” o bien no existen!.  No olvidéis que la información es la de WIN32_DiskDrive.

MisDiscos

Para los mas profundos en búsqueda de información mas “Fisica” podeis cambiar la “query” por la de Win32_PhysicalMedia.

Private MisDiscos As New ManagementObjectSearcher(«SELECT * FROM Win32_PhysicalMedia»)

Espero vuestras conversaciones J
Cuidaros,
Pep Lluis,

Imports System.Management

 

Public Class Form1

   

    ‘Obtener toda la informacion de mis discos (Logicos)

    Private MisDiscos As New ManagementObjectSearcher(«SELECT * FROM Win32_DiskDrive»)

    ‘Almacen del valor de las caracteristicas segun propiedad

    Private DiscInfo As New ManagementObject

 

    Private Sub Form1_Load(…..) Handles MyBase.Load

        Dim MiInfo = From Hd As ManagementObject In MisDiscos.Get Select Hd

        ‘Seleccionar la info del disco(0)

        ‘O bien proporcionar un combo para su seleccion
        DiscInfo = MiInfo(0)

        ‘Obtener el nombre de la propiedad

        ‘Rellenar el DUD con los nombres

        Me.DomainUpDown1.Items.AddRange( _

           ( _

              From Pn As Management.PropertyData _

              In DiscInfo.Properties _

              Select Pn.Name _

            ).ToArray)

        ‘Por defecto seleccionar el primer indice

        Me.DomainUpDown1.SelectedIndex = 1

    End Sub

   

    ‘ Al cambiar el indice del item seleccionado…

   

    Private Sub DomainUpDown1_SelectedItemChanged() _
         
Handles DomainUpDown1.SelectedItemChanged

        Try

            ‘obtener la descripcion de la propiedad

            Descripcion.Text = DiscInfo.Properties(Me.DomainUpDown1.Text).Value

        Catch ex As Exception

            ‘en caso de error…

            Descripcion.Text = «¿?»

        End Try

    End Sub

End Class

AndAlso? What Else!

Muchos de nosotros, sobre todo los históricos de VB, hemos pasado días enteros escribiendo sentencias donde abundan un buen numero de liados entramados de condicionales…

If Expresion1 And (Not Expresion2) And Expresion3 Then ….

Es normal dentro de nuestra concentración al escribir código, que pongamos nuestro foco de atención en resolver el planteamiento más que en imaginarnos lo que ocurre en el momento de su ejecución. Sin ir más lejos cuántos de nosotros nos abstraemos del algoritmo y pensamos en las miles o millones de veces que llegara a ejecutarse la evaluación de dichas expresiones. Y cuántos de nosotros  a pesar de ejecutarse en un procesador capaz de recorrer  millones de Instrucciones por segundo, intentamos abstraernos en un pensamiento “ecologista” en tanto a no malbaratar la circulación inútil de ‘bitios’. La respuesta es “Algunos de nosotros SI pensamos en todo esto” y como no, VB también!

Ahora toca preguntarnos ¿y esto que viene a contarnos?… la respuesta seria pues AndAlso, what else!

Cuando detrás de un condicional ‘If’ agrupamos varias expresiones enlazadas con operadores, a saber ‘Or’… ‘And’, debemos tener muy en cuenta que el resultado será fruto de la evaluación de todos ellos con el consecuente consumo de procesador.

Expresión 1

AND Expresión 2

Resultado

Verdadero

Verdadero

Verdadero

Verdadero

Falso

Falso

Falso

Verdadero

Falso

Falso

Falso

Falso

 

Pero para que tanto ruido?
Intentando buscar justificaciones, escribiendo un poquito más tendremos a nuestra disposición ‘AndAlso’

Expresión 1

ANDALSO Expresión 2

Resultado

Verdadero

Verdadero

Verdadero

Verdadero

Falso

Falso

Falso

No se Evalúa

Falso

 

Aun así seguro que mas de uno ponéis cara de extrañados, bien el matiz se encuentra en que “No se Evalúa” significa que “No se procesa” por lo que si encadenamos varias evaluaciones de expresiones con ‘and’, usando ‘andalso’ ahorraremos en consumo de proceso, por lo que solo continuara evaluando las expresiones si la precedente es ‘Verdadera’ y finalizara la evaluación del resto de expresiones al obtener el primer ‘falso’.

Sin duda simpáticas historias.
Pep Lluis,

Por Cierto os he hablado de ‘OrElse’… vaya! pues tambien existe!

Expresión 1

Expresión 2

Resultado

Verdadero

No se evalúa

Verdadero

Falso

Verdadero

Verdadero

Falso

Falso

Falso

Lo de WhatElse vamos a dejarlo para otro dia jajajajaja.

Una simple cuestión de hilos.

A cuerda de una pregunta en el foro (para principiantes),  donde se cuestiona porque el ‘timer’ deja de funcionar y no refresca el paso de los segundos cuando efectuamos una llamada a un procedimiento… vamos a exponer el siguiente argumento para intentar esclarecerlo.

Nuestro ‘Form’ se está rondando en su hilo de ejecución… por lo que cuando efectúas la llamada para «procesar la rutina», el ‘timer’ deja de refrescarse por falta de turno de ejecución al estar (nuestro hilo) ocupado en espera de recibir el retorno de la llamada a tal procedimiento.

Para no bloquear nuestro hilo de ejecución y poder continuar con otras tareas, deberemos llamar a ese proceso creando un nuevo hilo de ejecución, utilizando ‘Threading.Thread’ … aquí dejo un ejemplo donde muestra las dos situaciones de una forma muy básica.

En situación de ejecución, nuestro ‘form’ visualiza la fecha y hora actual en la barra de titulo. Al pulsar sobre el botón 1 se lanza la llamada al procedimiento ‘readline’ en espera de leer una línea recibida por el puerto serie, todo el ‘form’ quedara congelado hasta recibir esa línea, que de buena tinta sabemos que nunca llegara J  por lo tanto la barra de titulo quedara inanimada, pues el hilo está ocupado y el ‘timer1’ no dispone de turno de ejecución para dispar los eventos ‘tick’.

Sin embargo al hacer clic sobre el segundo botón, este crea un nuevo hilo de ejecución que apunta al mismo procedimiento pero con una nueva asignacion de ejecucion, haciendo autónomo su proceso en la llamada al procedimiento, así pues en este caso la barra de titulo reflejara en todo momento la fecha y hora, con independencia de si el procedimiento a finalizado o no, pues el hilo principal del ‘form’ continuara atendiendo y repartiendo la ejecución entre todos los objetos que tiene a su cargo… inclusive el nuevo hilo.

Para rodar este ejemplo, solo tienes que crear un nuevo proyecto ‘winform’ añadir un ‘timer’ y dos ‘Button’.

Espero que os sea útil y pido ‘sorrys’ por el rollo!
Pep Lluis,

Public Class Form1
    Private Puerto As New System.IO.Ports.SerialPort

    Private Sub Form1_Load(…..) Handles MyBase.Load
        Me.Timer1.Interval = 1000
        Me.Timer1.Enabled = True
        Me.Button1.Text = «Llamar Procedimiento»
        Me.Button2.Text = «Ejecutar nuevo Hilo»
        Puerto = My.Computer.Ports.OpenSerialPort(«COM1»)
    End Sub


    Private Sub Timer1_Tick(…..) Handles Timer1.Tick
        Me.Text = Date.Now
    End Sub

    Private Sub Button1_Click(…..) Handles Button1.Click
        Me.Button1.Enabled = False
        Me.Text = «*Ejecucion sin crear Hilo «
        Procedimiento()
        Me.Button1.Enabled = True
    End Sub

    Private Sub Button2_Click(…..) Handles Button2.Click
        Me.Button2.Enabled = False
        Me.Text = «*Ejecutar creando un nuevo Hilo»
        Dim MiHilo As New Threading.Thread(AddressOf Procedimiento)
        MiHilo.Start()
        ‘el timer continua con su ejecucion…        
        ‘Antes de lanzar una nueva llamada
        ‘deberiamos cancelar el hilo en espera
        ‘ejecutando : MiHilo.Abort() o controlando
        ‘su estado o control por ejemplo con :
        MiHilo.IsAlive
        MiHilo.Suspend()
        MiHilo.Sleep()
    End Sub

    Private Sub Procedimiento()
       
        ‘Esta funcion esta efectuando una llamada
        ‘a un procedimento que no finalizara hasta
        ‘completarse o exceder su tiempo de espera.
        Dim datos = Puerto.ReadLine
    End Sub
End
Class

Un Combo, Una MDB, Un DataGridView y una MDF

Aquí una idea de cómo utilizar MDF y MDB’s.

En este ejemplo utilizamos la tabla de proveedores de una MDB para rellenar un DataGridView de los productos del proveedor en la MDF de ‘NorthWnd’ seleccionado en el Combo. 

Combo+Datagrid

Debo advertir que el siguiente codigo no ejemplo de metodologia, tan solo pretende enseñar en un solo ejemplo como conectar una BD Access y otra de SQL, pero en ningun caso es un modelo de uso, pues en realidad nunca he trabajado con una aplicacion que utilice los dos formatos conjuntamente.

Imports System.Data.OleDb

Imports System.Data.SqlClient

 

Public Class Form1

    Private WithEvents ComboBox1 As New ComboBox

    Private WithEvents DataGridView1 As New DataGridView

   

    ‘Definir enlace a datos y objetos del form

    Private SQLConexion As New SqlConnection( _

        «Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Temp\Northwnd.mdf» + _

        «;Integrated Security=True;Connect Timeout=30;User Instance=True»)

 

    Private MDBConexion As New OleDbConnection( _
        «Provider=Microsoft.Jet.OLEDB.4.0;» + _

        «Data Source=C:\Temp\bd1.mdb»)

 

    Private Sub Form1_Load() Handles Me.Load

        Me.Controls.Add(ComboBox1)

        Me.ComboBox1.Dock = DockStyle.Top

        AddHandler ComboBox1.SelectedIndexChanged, AddressOf Obtener_Articulos

 

        Me.Controls.Add(Me.DataGridView1)

        Me.DataGridView1.Dock = DockStyle.Fill

 

        Me.ComboBox1.DisplayMember = «CompanyName»

        Me.ComboBox1.ValueMember = «SupplierID»

        Me.ComboBox1.DataSource = Obtener_Proveedores()

    End Sub

   

    ‘ Cargar el DGV con la seleccion de articulos segun el proveedor

    Private Sub Obtener_Articulos()

        Dim Articulos = _
          «SELECT * FROM Products Where SupplierId = « + _
          ComboBox1.SelectedValue.ToString

        SQLConexion.Open()

        Dim MiSqladapter As New SqlDataAdapter

        MiSqladapter.SelectCommand = New SqlCommand(Articulos, SQLConexion)

        Dim MiTabla As New DataTable()

        MiSqladapter.Fill(MiTabla)

        SQLConexion.Close()

        Me.DataGridView1.DataSource = MiTabla

    End Sub

   

    ‘ Obtener la tabla de proveedores como ‘datasource del ComboBox’

    Private Function Obtener_Proveedores()

        MDBConexion.Open()

        Dim MDBadapter As New OleDbDataAdapter(«Select * from Suppliers», MDBConexion)

        Dim MiTabla As New DataTable()

        MDBadapter.Fill(MiTabla)

        Return MiTabla

    End Function

 

End Class

El proveedor ‘Microsoft.Jet.OLEDB.4.0’ no está registrado en el equipo local

Sorprendentemente continúan llegando inquietudes preguntando cómo se abre una BD de Access en las nuevas versiones de VB.  Algunos asiduos a este formato han sufrido el desconcertante mensaje… no está en el equipo local? Cuando la realidad es que no esta implementado!

Para dar una buena explicación, recibimos este mensaje cuando utilizamos ‘OLEDB’ en un sistema X64 y ese es el detalle. No existe una implementación de ‘OLEDB’ para 64 bits.

La única solución es desarrollar en 32Bits, aunque esto ultimo NO signifique que tengamos que reinstalar el sistema operativo… tan solo nesitaremos seleccionar ‘X86’ como ‘CPU de destino’ en las ‘Opciones de Compilación Avanzadas’ de la pestaña ‘Compilar’ en las propiedades de ‘My Project’

Espero que esto os ahorre alguna que otra hora de busqueda.
Pep Lluis,

Error de sintaxis en la instrucción INSERT INTO.

Este es uno de los textos de error que mas amenudo se enfrenta a los que intentan actualizar la informacion enlazada de un DGV’s y una MDB.

Aunque en muchos otros foros/post se advierte de debemos utilizar nombres de campo que no esten reservados, caemos y volvemos a caer en el error de usar nombres con caracteres no admitidos. Un simple espacio al nombrar el campo provocara una excepcion tanto en la operación de ‘INSERT’ Como ‘UPDATE’. Suerte que a grandes males… grandes remedios J

Ejemplo :   el Nombre ‘Columna A’ generara una excepcion
Sin embargo  el nombre ‘Columna_A’ no genera ninguna excepcion… asi de simple.

Os recuerdo el enlace con la lista de palabras reservadas que no pueden utilizarse para nombrar los campos de una MDB que posteriormente utilizaremos enlazada con un DataGridView y un ‘OleDb.OleDbCommandBuilder(MiMdbAdaptador)’

http://support.microsoft.com/kb/248738

En caso contrario las únicas opciones disponibles para continuar utilizando dichos nombres, será construir el’INSERT’… ‘UPDATE’ commands de forma manual o utilizar la opción de ‘Origen de Datos’ generado por Visual Studio.

Saludos,
Pep Lluis,

Yo solo quiero Numeros!

Independientemente de las mil y una formas para filtrar/formatear entradas de texto, me gustan las sencillas sin retorcimientos. Aquí te dejo una idea de cómo aplicar reglas cuando se trata de todo un form, aunque trabajandolo puedes customizar el comportamiento en funcion al control que tiene el foco. No olvides que tambien dispones de un espacio de nombres sensacional :

Imports System.Text.RegularExpressions

Aunque como te digo, en determinadas ocasiones cabe aplicar lo sencillo si con ello cubrimos las necesidades. 😉
El siguiente ejemplo demuestra como filtrar la pulsación de cualquier tecla que no sea numerica o coma.

Private Sub Form1_Load() Handles MyBase.Load
    Me.KeyPreview = True
End Sub 

Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
    Select Case keyData
        ‘ 48 a 57  = numericas encima teclado alfabetico
        ‘ 97 a 106 = Numericas teclado numerico
        Case 48 To 57, 97 To 106, Keys.Oemcomma
            ‘Solo devolver las pulsaciones que pasan el filtro
            Return MyBase.ProcessDialogKey(keyData)
        Case Else
            ‘Evitar la propagacion de la pulsacion
            ‘de teclas que no nos interesan
            Return True
    End Select
End Function

Lo Bueno y simple… Dos veces bueno!
Pep Lluis