El código básico para dibujar una matriz lo conseguí de este enlace. Pero yo necesitaba dibujar una matriz como la siguiente:
El código en Latex para dibujarla es:
\[ \left(
\begin{array}{cccc}
b\textsubscript{11} & b\textsubscript{12} & ... & b\textsubscript{1n} \\
b\textsubscript{11} & b\textsubscript{12} & ... & b\textsubscript{1n} \\
\vdots & \vdots & \vdots & \vdots \\
b\textsubscript{n1} & b\textsubscript{n2} & ... & b\textsubscript{nn}
\end{array}
\right)\]
Luego tenía que dibujar una matriz como combinación de columnas multiplicadas por un escalar, como la siguiente:
El código es:
\[b= \left(
\begin{array}{c|c|c|c|c}
&&&& \\
&&&& \\
u\textsubscript{1}\mbox{. \={v}} & u\textsubscript{2}\mbox{. \={v}} & u\textsubscript{3}\mbox{. \={v}} &...& u\textsubscript{n}\mbox{. \={v}}\\
&&&& \\
&&&&
\end{array}
\right)\]
Códigos de ejemplo para aprender distintas tecnologías, o lo que sucede cuando a una cuarentona se la deja sola con una computadora
Acerca de:
Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)
sábado, 22 de marzo de 2014
sábado, 1 de marzo de 2014
jueves, 20 de febrero de 2014
Continuando con el Conjunto de Wirth...
Actualización de Electrónica a Martillazos, hallé algunas cosas interesantes con respecto al algoritmo de PuntoPeek para calcular el Conjunto de Wirth.
El enlace aquí.
Un mirror aquí.
El enlace aquí.
Un mirror aquí.
lunes, 13 de enero de 2014
Resetear campo autoincrementable (serial) en Postgre 9.3
Tengo una base de datos llamada "Prueba" con una tabla "phonebook", la cual tiene un campo autoincrementable (tipo serial) llamado "ID":
Cuando se crea un dato serial usando el pgAdmin, Postgre automáticamente nos crea una secuencia (en este caso llamada "phonebook_ID_seq") a la cual el campo serial está vinculado mediante la siguiente instrucción:
ALTER TABLE phonebook ALTER COLUMN "ID" SET DEFAULT nextval('"phonebook_ID_seq"'::regclass);
Para Postgre, un dato serial es un dato Integer con la función "nextval".
Esta es mi situación:
Luego de añadir y borrar varios registros a la tabla "phonebook", y finalmente dejarla vacía, quiero resetear el valor del campo "ID" a 1.
Al igual que en MySql, Postgre tiene una función llamada "setval" que me permite ponerle un valor arbitrario a la secuencia desde el cual continuará con los incrementos.
En el pgAdmin seleccionamos el campo "ID", abrimos la ventana de queries mediante el botón "Execute Arbitrary Queries" (el que tiene una lupa y el texto "SQL"), e ingresamos el siguiente query:
select setval('"phonebook_ID_seq"',1);
Hay que notar que lo que se altera es la secuencia, no el campo "ID". Hay que tener cuidado de poner el nombre de la secuencia entre comillas dobles dentro de las comillas simples. Como Postgre es Case Sensitive, saltarán errores si omitimos las comillas dobles y si el nombre de la secuencia contiene mayúsculas.
En la ventana de queries quedará así:
Si todo sale bien, nos aparecerá el valor al que hemos reseteado la secuencia. No tiene que ser 1, puede ser cualquier valor que queramos.
Cuando se crea un dato serial usando el pgAdmin, Postgre automáticamente nos crea una secuencia (en este caso llamada "phonebook_ID_seq") a la cual el campo serial está vinculado mediante la siguiente instrucción:
ALTER TABLE phonebook ALTER COLUMN "ID" SET DEFAULT nextval('"phonebook_ID_seq"'::regclass);
Para Postgre, un dato serial es un dato Integer con la función "nextval".
Esta es mi situación:
Luego de añadir y borrar varios registros a la tabla "phonebook", y finalmente dejarla vacía, quiero resetear el valor del campo "ID" a 1.
Al igual que en MySql, Postgre tiene una función llamada "setval" que me permite ponerle un valor arbitrario a la secuencia desde el cual continuará con los incrementos.
En el pgAdmin seleccionamos el campo "ID", abrimos la ventana de queries mediante el botón "Execute Arbitrary Queries" (el que tiene una lupa y el texto "SQL"), e ingresamos el siguiente query:
select setval('"phonebook_ID_seq"',1);
Hay que notar que lo que se altera es la secuencia, no el campo "ID". Hay que tener cuidado de poner el nombre de la secuencia entre comillas dobles dentro de las comillas simples. Como Postgre es Case Sensitive, saltarán errores si omitimos las comillas dobles y si el nombre de la secuencia contiene mayúsculas.
En la ventana de queries quedará así:
Si todo sale bien, nos aparecerá el valor al que hemos reseteado la secuencia. No tiene que ser 1, puede ser cualquier valor que queramos.
miércoles, 8 de enero de 2014
Postgre 9.3: Errores 42501 y 42703:
Tengo la siguiente base de datos Prueba instalada en un servidor local de Postgre versión 9.3, la cual tiene una sola tabla "phonebook" cuya estructura copié de algún sitio de Internet (al instalar Postgre se tiene la opción de instalar también el pgAdmin):
El Owner de la base de datos y de la tabla es el superusuario "postgre". La base de datos Prueba tiene como esquema por defecto (Default Schema) igual a público (public), también sus privilegios son públicos.
También he creado un usuario "user01" con las siguientes propiedades:
Al conectar una aplicación en C# mediante el usuario "user01", usando Npgsql (el cual se puede instalar junto con el Postgre usando la aplicación Stack Builder que también viene con el instalador del Postgre) y luego de ver los datos de la tabla phonebook todo iba bien; pero cuando quería modificar la tabla phonebook con un update, insert ó delete me arrojaba el siguiente error:
"Error 42501: permiso denegado a la secuencia phonebook_ID_seq"
Este error salta si el usuario con el que intento modificar la tabla no es su dueño (owner). No interesa si la base de datos tiene como dueño al superusuario "postgre", la tabla debe tener como dueño al usuario que intenta modificarla.
Para cambiar al dueño de la tabla phonebook de "postgre" a "user01" basta este script:
ALTER TABLE phonebook
OWNER TO user01;
Y entonces al usar la siguiente sentencia insert desde C#:
string query = @"insert into phonebook (phone, firstname, lastname, address) values ('1234', 'Wert', 'Asdlo', 'Fake Street 123')";
Los datos se guardaban correctamente, pero al querer actualizar o borrar:
string query1 = @"Update phonebook set phone ='0000', firstname ='Carry', lastname ='Doe', address = 'No signed' where ID = 1";
string query2 = "delete from phonebook where ID = 1";
Me saltaba el siguiente error:
"Error 42703: no existe la columna id"
Lo extraño es que la tabla phonebook sí tiene una columna llamada "ID". Buscando por internet, hallé aquí la solución: se debe poner el nombre del campo que contiene mayúsculas entre comillas:
string query1 = "Update phonebook set phone ='0000', firstname ='Carry', " +
" lastname ='Doe', address = 'No signed' where \"ID\" = 1";
string query2 = "delete from phonebook where \"ID\" = 1";
El caracter \ le indica al C# que la comilla que le sigue no indica el final de la cadena. El motor del Postgre convierte todos los nombres de las columnas en una sentencia sql a minúsculas. Por ahí leí que, internamente, Postgre es Case Sensitive.
El Owner de la base de datos y de la tabla es el superusuario "postgre". La base de datos Prueba tiene como esquema por defecto (Default Schema) igual a público (public), también sus privilegios son públicos.
También he creado un usuario "user01" con las siguientes propiedades:
Al conectar una aplicación en C# mediante el usuario "user01", usando Npgsql (el cual se puede instalar junto con el Postgre usando la aplicación Stack Builder que también viene con el instalador del Postgre) y luego de ver los datos de la tabla phonebook todo iba bien; pero cuando quería modificar la tabla phonebook con un update, insert ó delete me arrojaba el siguiente error:
"Error 42501: permiso denegado a la secuencia phonebook_ID_seq"
Este error salta si el usuario con el que intento modificar la tabla no es su dueño (owner). No interesa si la base de datos tiene como dueño al superusuario "postgre", la tabla debe tener como dueño al usuario que intenta modificarla.
Para cambiar al dueño de la tabla phonebook de "postgre" a "user01" basta este script:
ALTER TABLE phonebook
OWNER TO user01;
Y entonces al usar la siguiente sentencia insert desde C#:
string query = @"insert into phonebook (phone, firstname, lastname, address) values ('1234', 'Wert', 'Asdlo', 'Fake Street 123')";
Los datos se guardaban correctamente, pero al querer actualizar o borrar:
string query1 = @"Update phonebook set phone ='0000', firstname ='Carry', lastname ='Doe', address = 'No signed' where ID = 1";
string query2 = "delete from phonebook where ID = 1";
Me saltaba el siguiente error:
"Error 42703: no existe la columna id
Lo extraño es que la tabla phonebook sí tiene una columna llamada "ID". Buscando por internet, hallé aquí la solución: se debe poner el nombre del campo que contiene mayúsculas entre comillas:
string query1 = "Update phonebook set phone ='0000', firstname ='Carry', " +
" lastname ='Doe', address = 'No signed' where \"ID\" = 1";
string query2 = "delete from phonebook where \"ID\" = 1";
El caracter \ le indica al C# que la comilla que le sigue no indica el final de la cadena. El motor del Postgre convierte todos los nombres de las columnas en una sentencia sql a minúsculas. Por ahí leí que, internamente, Postgre es Case Sensitive.
sábado, 14 de diciembre de 2013
Cómo Convertir de long a LPCWSTR (puntero largo a Wide String constante) en Visual C++
Todo empezó cuando quise aprender a usar las apis GetWindowRect y GetClientRect. La primera devuelve las coordenadas que ocupa la ventana, la segunda devuelve las coordenadas que ocupa la ventana sin la barra de título.
Como práctica, quise calcular el alto de la barra de título de una ventana.
El valor calculado es del tipo long. Luego debía convertirlo a LPCWSTR para pasarlo como parámetro a la api setWindowText que lo escribirá en lugar del título de la ventana.
He usado la información que hallé en estas webs:
La función ltoa (reemplazada por _ltoa)
Convertir de char* a LPCWSTR
La función MultiByteToWideChar
El código es el siguiente:
En el caso de una aplicación tipo win32, coloqué este código dentro de la función que procesa los mensajes de la ventana (WndProc), exactamente en el mensaje que se envía al crearla:
Al ejecutar el programa, mostrará el alto de la barra de título en el texto de... la barra de título.
Como práctica, quise calcular el alto de la barra de título de una ventana.
El valor calculado es del tipo long. Luego debía convertirlo a LPCWSTR para pasarlo como parámetro a la api setWindowText que lo escribirá en lugar del título de la ventana.
He usado la información que hallé en estas webs:
La función ltoa (reemplazada por _ltoa)
Convertir de char* a LPCWSTR
La función MultiByteToWideChar
El código es el siguiente:
RECT
r1, r2;
GetWindowRect(hWnd,
&r1);
GetClientRect(hWnd,
&r2);
long
alto1 = r1.bottom - r1.top;
long
alto2 = r2.bottom - r2.top;
long
alto3 = alto1-alto2;
//
convertir long a Wide WCHAR*
int
size=sizeof(long)*8+1;
char*
texto = new
char[size];
WCHAR*
texto2 = new
WCHAR[size];
_ltoa(alto3,texto,10);
MultiByteToWideChar(CP_UTF8,
0, texto, -1, texto2, size);
//
fin de la conversión. Para convertir de WCHAR* a LPCWSTR (puntero
largo a Const Wide String) basta un casteo
SetWindowText(hWnd,
(LPCWSTR)texto2);
En el caso de una aplicación tipo win32, coloqué este código dentro de la función que procesa los mensajes de la ventana (WndProc), exactamente en el mensaje que se envía al crearla:
Al ejecutar el programa, mostrará el alto de la barra de título en el texto de... la barra de título.
sábado, 23 de noviembre de 2013
Implementación Thread-safe de una clase Singleton
Entrada original de WhatILearntToday: "El patrón Singleton se usa cuando queremos que una clase permita definir una, y sólo una, instancia de esa misma clase".
La implementación WhatILearntToday de una clase Singleton Thread-Safe es la siguiente:
Mi implementación (también Thread-Safe) es:
La implementación WhatILearntToday de una clase Singleton Thread-Safe es la siguiente:
public class SingletonClass
{
private SingletonClass()
{
}
//Implementation #1 NO Thread-Safe: puede fallar si varios hilos intentan instanciarla al mismo tiempo
//static SingletonClass _instance = null;
//public static SingletonClass GetInstance()
//{
// if (_instance == null)
// {
// _instance = new SingletonClass();
// }
// return _instance;
//}
//Implementation #2 Thread-safe
static readonly SingletonClass _instance = new SingletonClass();
public static SingletonClass GetInstance()
{
get
{
return _instance;
}
}
public string GetWelcomeMessage()
{
return "Welcome to the Singleton world!! ";
}
}
Mi implementación (también Thread-Safe) es:
public class SingletonClass
{
private SingletonClass()
{
}
static readonly SingletonClass _instance = null;
static object lockThis; public static SingletonClass GetInstance() { lock(lockThis) {
if (_instance == null)
_instance = new SingletonClass();
}
return _instance;
}
public string GetWelcomeMessage()
{
return "Welcome to the Singleton world!! ";
}
}
miércoles, 23 de octubre de 2013
Cómo evadir la limitación de tamaño de una ventana en Windows
Por diseño, Microsoft Windows limita el tamaño de las ventanas a (en píxeles):
(12 + ancho de la resolución de pantalla) x (12 + alto de la resolución de pantalla)
Más información en StackOverflow.
Por allí hallé quienes afirman que se puede superar esta restricción. Y entonces me topé con este código, de la misma Microsoft, en Visual Basic 6.
Lo copio aquí para que no se vaya a perder:
En un módulo bas:
El truco es fácil: donde están los números en rojo, escribimos nuestros números enormes favoritos. Yo le puse por código a una ventana (Form) dimensiones de 2050*1600 píxeles, en una resolución de pantalla de 1024*768 (la restricción por defecto sería 1036*780).
Para hacer esto en el form ponemos:
Y funcionó.
Ya no intenté con dimensiones mayores porque una ventana con aproximadamente el doble de alto y ancho que la resolución de pantalla parece ser suficientemente grande. Deduzco que el máximo que puede aguantar el sistema operativo depende de la memoria máxima que le puede asignar a semejante ventanón y antes que la RAM empiece a echar humo.
Como son puras llamadas a Apis de WIndows, se puede traducir este código a Visual C++ o a .Net usando DLLImport.
(12 + ancho de la resolución de pantalla) x (12 + alto de la resolución de pantalla)
Más información en StackOverflow.
Por allí hallé quienes afirman que se puede superar esta restricción. Y entonces me topé con este código, de la misma Microsoft, en Visual Basic 6.
Lo copio aquí para que no se vaya a perder:
En un módulo bas:
Option Explicit
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type MINMAXINFO
ptReserved As POINTAPI
ptMaxSize As POINTAPI
ptMaxPosition As POINTAPI
ptMinTrackSize As POINTAPI
ptMaxTrackSize As POINTAPI
End Type
Global lpPrevWndProc As Long
Global gHW As Long
Private Declare Function DefWindowProc Lib "user32" Alias _
"DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Sub CopyMemoryToMinMaxInfo Lib "KERNEL32" Alias _
"RtlMoveMemory" (hpvDest As MINMAXINFO, ByVal hpvSource As Long, _
ByVal cbCopy As Long)
Private Declare Sub CopyMemoryFromMinMaxInfo Lib "KERNEL32" Alias _
"RtlMoveMemory" (ByVal hpvDest As Long, hpvSource As MINMAXINFO, _
ByVal cbCopy As Long)
Public Sub Hook()
'Start subclassing.
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
'Cease subclassing.
temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim MinMax As MINMAXINFO
'Check for request for min/max window sizes.
If uMsg = WM_GETMINMAXINFO Then
'Retrieve default MinMax settings
CopyMemoryToMinMaxInfo MinMax, lParam, Len(MinMax)
'Specify new minimum size for window.
MinMax.ptMinTrackSize.x = 200
MinMax.ptMinTrackSize.y = 200
'Specify new maximum size for window.
MinMax.ptMaxTrackSize.x = 500
MinMax.ptMaxTrackSize.y = 500
'Copy local structure back.
CopyMemoryFromMinMaxInfo lParam, MinMax, Len(MinMax)
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, _
wParam, lParam)
End If
End Function
El truco es fácil: donde están los números en rojo, escribimos nuestros números enormes favoritos. Yo le puse por código a una ventana (Form) dimensiones de 2050*1600 píxeles, en una resolución de pantalla de 1024*768 (la restricción por defecto sería 1036*780).
Para hacer esto en el form ponemos:
Option Explicit
Private Sub Form_Load()
'Save handle to the form.
gHW = Me.hwnd
'Begin subclassing.
Hook
' le ponemos un tamaño ENORME
Me.Height = 1600
Me.Width = 2050
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Stop subclassing.
Unhook
End Sub
Y funcionó.
Ya no intenté con dimensiones mayores porque una ventana con aproximadamente el doble de alto y ancho que la resolución de pantalla parece ser suficientemente grande. Deduzco que el máximo que puede aguantar el sistema operativo depende de la memoria máxima que le puede asignar a semejante ventanón y antes que la RAM empiece a echar humo.
Como son puras llamadas a Apis de WIndows, se puede traducir este código a Visual C++ o a .Net usando DLLImport.
sábado, 12 de octubre de 2013
Cómo importar datos con carácteres internacionales desde xls a SQLite
Tengo el siguiente archivo xls:
y quiero pasar los datos a una tabla en SQLite.
Después de probar distintas aplicaciones para SQLite, descubrí que ninguna importa directamente desde el formato xls (al menos no las que son gratuitas), pero sí importan desde el formato csv.
Tanto MSExcel como OpenOffice Calc pueden exportar datos al formato csv. Pero hay que tener en consideración un par de detalles para no perder los carácteres internacionales.
Para este ejemplo estoy usando OpenOffice Calc 3, pero el procedimiento es muy similar para MS Excel.
En "Guardar Como" elegimos el formato csv. Aparecerá la siguiente ventana:
Los datos deben exportarse con la codificación UTF8 y estar entrecomillados.
Para importar los datos a una base de datos en SQLite, el mejor programa que hallé es el Add-On para Firefox SQLite Manager.
Una vez instalado, lo ejecutamos desde Firefox -> Herramientas -> SQLite Manager (yo uso la versión 0.8.0) y cargamos nuestra base de datos, o la creamos.
Si la creamos no añadimos ninguna tabla, los datos importados crearán una automáticamente (mi base de datos se llama "Prueba01").
Luego vamos a la opción Base de Datos -> importar, o al ícono celeste con la flechita al costado del ícono de Abrir:
Elegimos la pestaña "CSV". Con el botón "Seleccionar Archivo" escogemos el archivo csv donde hemos exportado los datos desde xls. Las opciones a elegir son:
- Tipo de Codificación: UTF-8
- La primera fila contiene los nombres de las columnas
- Campos separados por coma
- Campos limitados por comillas dobles, siempre.
- Le cambié el nombre a la nueva tabla de "sample sales" a "sample_sales". Es mejor que las tablas no tengan nombres con espacios.
Presionamos OK. Aparecerá esta ventanita:
En mi caso, como los datos de "CategoryID" se repiten, debo deseleccionar las opciones "Clave Primaria" "Auto Inc" y "única" si no botará error (y uno bastante feo). Estas opciones se seleccionan sólo si los datos correspondientes son únicos, no hay valores en blanco, y pueden convertirse a enteros.
En una bse de datos SQLIte es mejor no usar el formato DateTime. Lo mejor es guardar las fechas como texto, y recién realizar la conversión en nuestra aplicación. Así se evitan excepciones que se producen en el driver de SQLite y no en nuestro código (esta recomendación es de la misma web de SQLite, y la aprendí después de jugar un poco con el C# y aventar algunas hermosas excepciones de formato...).
Si todo sale bien, nuestros datos se verán así, ya dentro de la base de datos:
Si no se declara una clave primaria, el SQLite Manager nos creará una :D en este caso es "rowid". Y como se puede ver, los carácteres internacionales se conservan intactos.
Ya paratrastear administrar la base de datos, prefiero usar el SQLite Studio.
y quiero pasar los datos a una tabla en SQLite.
Después de probar distintas aplicaciones para SQLite, descubrí que ninguna importa directamente desde el formato xls (al menos no las que son gratuitas), pero sí importan desde el formato csv.
Tanto MSExcel como OpenOffice Calc pueden exportar datos al formato csv. Pero hay que tener en consideración un par de detalles para no perder los carácteres internacionales.
Para este ejemplo estoy usando OpenOffice Calc 3, pero el procedimiento es muy similar para MS Excel.
En "Guardar Como" elegimos el formato csv. Aparecerá la siguiente ventana:
Los datos deben exportarse con la codificación UTF8 y estar entrecomillados.
Para importar los datos a una base de datos en SQLite, el mejor programa que hallé es el Add-On para Firefox SQLite Manager.
Una vez instalado, lo ejecutamos desde Firefox -> Herramientas -> SQLite Manager (yo uso la versión 0.8.0) y cargamos nuestra base de datos, o la creamos.
Si la creamos no añadimos ninguna tabla, los datos importados crearán una automáticamente (mi base de datos se llama "Prueba01").
Luego vamos a la opción Base de Datos -> importar, o al ícono celeste con la flechita al costado del ícono de Abrir:
Elegimos la pestaña "CSV". Con el botón "Seleccionar Archivo" escogemos el archivo csv donde hemos exportado los datos desde xls. Las opciones a elegir son:
- Tipo de Codificación: UTF-8
- La primera fila contiene los nombres de las columnas
- Campos separados por coma
- Campos limitados por comillas dobles, siempre.
- Le cambié el nombre a la nueva tabla de "sample sales" a "sample_sales". Es mejor que las tablas no tengan nombres con espacios.
Presionamos OK. Aparecerá esta ventanita:
Oh! ¡Aquí hay algo qué resaltar!
En mi caso, como los datos de "CategoryID" se repiten, debo deseleccionar las opciones "Clave Primaria" "Auto Inc" y "única" si no botará error (y uno bastante feo). Estas opciones se seleccionan sólo si los datos correspondientes son únicos, no hay valores en blanco, y pueden convertirse a enteros.
En una bse de datos SQLIte es mejor no usar el formato DateTime. Lo mejor es guardar las fechas como texto, y recién realizar la conversión en nuestra aplicación. Así se evitan excepciones que se producen en el driver de SQLite y no en nuestro código (esta recomendación es de la misma web de SQLite, y la aprendí después de jugar un poco con el C# y aventar algunas hermosas excepciones de formato...).
Si todo sale bien, nuestros datos se verán así, ya dentro de la base de datos:
Si no se declara una clave primaria, el SQLite Manager nos creará una :D en este caso es "rowid". Y como se puede ver, los carácteres internacionales se conservan intactos.
Ya para
jueves, 8 de agosto de 2013
Cómo ignorar los acentos al hacer una búsqueda en una base de datos en MS Access (mdb) con C#
Tengo el siguiente código:
string nombre = nombreABuscarenlaBD;
string query = String.Concat("Select * from Tabla1 where campoNombre like '", nombre, "'");
Este query funciona mientras no se desee buscar un nombre que incluya acentos como "María" ingresando "Maria" . Lo peor: puede que el usuario ni siquiera sepa si en la base de datos los nombres están guardados con acentos o no.
Para que la búsqueda devuelva todas las coincidencias con y sin acentos, se debe hacer el siguiente cambio a la variable tipo string que contiene el criterio de búsqueda (la idea es sacada de este foro):
nombre = nombre.Replace("a", "[aá]").Replace("e", "[eé]").Replace("i", "[ií]").Replace("o", "[oó]").Replace("u", "[uú]").Trim();
Si se desea ignorar también las diéresis, será:
nombre = nombre.Replace("a", "[aäá]").Replace("e", "[eëé]").Replace("i", "[iïí]").Replace("o", "[oöó]").Replace("u", "[uüú]").Trim();
string nombre = nombreABuscarenlaBD;
string query = String.Concat("Select * from Tabla1 where campoNombre like '", nombre, "'");
Este query funciona mientras no se desee buscar un nombre que incluya acentos como "María" ingresando "Maria" . Lo peor: puede que el usuario ni siquiera sepa si en la base de datos los nombres están guardados con acentos o no.
Para que la búsqueda devuelva todas las coincidencias con y sin acentos, se debe hacer el siguiente cambio a la variable tipo string que contiene el criterio de búsqueda (la idea es sacada de este foro):
nombre = nombre.Replace("a", "[aá]").Replace("e", "[eé]").Replace("i", "[ií]").Replace("o", "[oó]").Replace("u", "[uú]").Trim();
Si se desea ignorar también las diéresis, será:
nombre = nombre.Replace("a", "[aäá]").Replace("e", "[eëé]").Replace("i", "[iïí]").Replace("o", "[oöó]").Replace("u", "[uüú]").Trim();
Suscribirse a:
Entradas (Atom)















