Primero declaramos las funciones SendMessage y capCreateCaptureWindow (si se declaran en un módulo .bas las declaraciones deben ser públicas, para este ejemplo asumiremos que todo el código está dentro de un Form):
Private Declare Function capCreateCaptureWindow Lib "avicap32.dll" _
Alias "capCreateCaptureWindowA" ( _
ByVal lpszWindowName As String, _
ByVal dwStyle As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal hwndParent As Long, _
ByVal nID As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Const CONNECT As Long = 1034
El código que nos dice si hay una webcam conectada es:
Dim mCapHwnd as Long
mCapHwnd = capCreateCaptureWindowA("WebCap", 0, 0, 0, 320, 240, Me.hwnd, 0)
DoEvents
If SendMessage(mCapHwnd, CONNECT, 0, 0) <> 0 Then
MsgBox "Se ha detectado una webcam conectada y lista para usarse"
Else
MsgBox "No se ha detectado una webcam"
End If
Basado en este código de Recursos Visual Basic
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 :)
jueves, 11 de abril de 2013
miércoles, 27 de marzo de 2013
Code Snippet: Pequeño ejemplo del uso de Linq.Any
Definición de Linq.Any extraído de esta web:
"El operador Any se utiliza para determinar si existe un elemento dentro de una secuencia que cumpla una condición expecífica."
Pero lo que yo necesitaba era un ejemplo concreto para saber si un elemento no existe en una colección usando Linq.Any.
El siguiente código muestra cómo usar Linq.Any para saber si un elemento existe o no en una colección. Es autoexplicativo:
using System;
using System.Linq;
using System.Collections.Generic;
namespace LinqPractice
{
class Program
{
static void Main(string[] args)
{
IEnumerable mis_nums = Enumerable.Range(0, 4);
mis_nums = mis_nums.Select(c => c * 3);
// mis_nums = {0, 3, 6, 9}
if (mis_nums.Any(c => c != 7))
Console.WriteLine("Existe al menos un número que es diferente de 7");
if (mis_nums.Any(c => c == 9))
Console.WriteLine("El 9 sí existe en la colección");
else
Console.WriteLine("El 9 no existe en la colección");
if (!mis_nums.Any(c => c == 7))
Console.WriteLine("El 7 no existe en la colección");
else
Console.WriteLine("El 7 sí existe en la colección");
Console.Read();
}
}
}
El resultado es:
"El operador Any se utiliza para determinar si existe un elemento dentro de una secuencia que cumpla una condición expecífica."
Pero lo que yo necesitaba era un ejemplo concreto para saber si un elemento no existe en una colección usando Linq.Any.
El siguiente código muestra cómo usar Linq.Any para saber si un elemento existe o no en una colección. Es autoexplicativo:
using System;
using System.Linq;
using System.Collections.Generic;
namespace LinqPractice
{
class Program
{
static void Main(string[] args)
{
IEnumerable
mis_nums = mis_nums.Select(c => c * 3);
// mis_nums = {0, 3, 6, 9}
if (mis_nums.Any(c => c != 7))
Console.WriteLine("Existe al menos un número que es diferente de 7");
if (mis_nums.Any(c => c == 9))
Console.WriteLine("El 9 sí existe en la colección");
else
Console.WriteLine("El 9 no existe en la colección");
if (!mis_nums.Any(c => c == 7))
Console.WriteLine("El 7 no existe en la colección");
else
Console.WriteLine("El 7 sí existe en la colección");
Console.Read();
}
}
}
El resultado es:
lunes, 11 de marzo de 2013
Visual C++: Cómo hacer que una ventana aparezca maximizada al cargarla
Para una aplicación tipo Win32 se debe buscar en la función Initinstance la línea donde dice ShowWindow:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Almacenar identificador de instancia en una variable global
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
// Visual C++ nos crea esta línea:
// ShowWindow(hWnd, nCmdShow);
// debemos reemplazarla por esta otra línea:
ShowWindow(hWnd, SW_MAXIMIZE);
UpdateWindow(hWnd);
return TRUE;
}
Los valores del parámetro que se le pasa a la api ShowWindow están declarados en WinUser.h y son los siguientes:
#define SW_HIDE 0
#define SW_SHOWNORMAL 1
#define SW_NORMAL 1
#define SW_SHOWMINIMIZED 2
#define SW_SHOWMAXIMIZED 3
#define SW_MAXIMIZE 3
#define SW_SHOWNOACTIVATE 4
#define SW_SHOW 5
#define SW_MINIMIZE 6
#define SW_SHOWMINNOACTIVE 7
#define SW_SHOWNA 8
#define SW_RESTORE 9
#define SW_SHOWDEFAULT 10
#define SW_FORCEMINIMIZE 11
#define SW_MAX 11
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Almacenar identificador de instancia en una variable global
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
// Visual C++ nos crea esta línea:
// ShowWindow(hWnd, nCmdShow);
// debemos reemplazarla por esta otra línea:
ShowWindow(hWnd, SW_MAXIMIZE);
UpdateWindow(hWnd);
return TRUE;
}
Los valores del parámetro que se le pasa a la api ShowWindow están declarados en WinUser.h y son los siguientes:
#define SW_HIDE 0
#define SW_SHOWNORMAL 1
#define SW_NORMAL 1
#define SW_SHOWMINIMIZED 2
#define SW_SHOWMAXIMIZED 3
#define SW_MAXIMIZE 3
#define SW_SHOWNOACTIVATE 4
#define SW_SHOW 5
#define SW_MINIMIZE 6
#define SW_SHOWMINNOACTIVE 7
#define SW_SHOWNA 8
#define SW_RESTORE 9
#define SW_SHOWDEFAULT 10
#define SW_FORCEMINIMIZE 11
#define SW_MAX 11
viernes, 22 de febrero de 2013
Algoritmo para obtener números primos de una forma funcional
Todo empezó cuando me puse a aprender Python (debido a que este curso requiere programar en ese lenguaje) utilizando Python Tools for Visual Studio. Primero debe bajarse e instalarse el Interpreter y, si no se tiene el Visual Studio, o se tiene la versión Express, hay que instalar The Visual Studio 2010 Shell Redistributable Package, y al final instalar Python Tools. Como resultado, tenemos un Python Express :D
Buscando tutoriales. hallé que en esta web proponían el siguiente método para obtener números primos (llamado "El Colador de Eratósthenes", no es el método más eficiente):
nums = range(2, 50)
for i in range(2, 8):
nums = filter(lambda x: x == i or x % i, nums)
Luego el autor dice: "No sé de algún lenguaje que pueda hacer lo mismo con sus características propias de una forma tan compacta y legible como en Python (excepto para lenguajes funcionales)".
¡Sorpresa! En C# sí se puede:
int[] nums = Enumerable.Range(2, 48).ToArray();
for (int i = 2; i < 8; i++)
nums = nums.Where(c => c == i || c % i != 0).ToArray();
Sólo hay que importar los espacios de nombres System y System.Linq.
:D
Buscando tutoriales. hallé que en esta web proponían el siguiente método para obtener números primos (llamado "El Colador de Eratósthenes", no es el método más eficiente):
nums = range(2, 50)
for i in range(2, 8):
nums = filter(lambda x: x == i or x % i, nums)
Luego el autor dice: "No sé de algún lenguaje que pueda hacer lo mismo con sus características propias de una forma tan compacta y legible como en Python (excepto para lenguajes funcionales)".
¡Sorpresa! En C# sí se puede:
int[] nums = Enumerable.Range(2, 48).ToArray();
for (int i = 2; i < 8; i++)
nums = nums.Where(c => c == i || c % i != 0).ToArray();
Sólo hay que importar los espacios de nombres System y System.Linq.
:D
lunes, 21 de enero de 2013
Tutorial: Creando una DLL en Visual C++ 2010 y Usándola en una Aplicación en C#
Electrónica a Martillazos, actualización de la sección de VB6 y C++:
Creando una DLL en Visual C++ 2010 y Usándola en una Aplicación en C#.
Link directo
Un mirror
:D
Creando una DLL en Visual C++ 2010 y Usándola en una Aplicación en C#.
Link directo
Un mirror
:D
martes, 15 de enero de 2013
El Control DataGridView lanza una System.ArgumentOutOfRangeException al recorrer sus filas
Tengo un DataGridView llamado dGridVIew al cual le añado datos de la siguiente manera:
DataRow[] dRow = MetodoQueDevuelveUnArrayDeDataRows();
object[] param = new object[3];
for (int i = 0; i < dRow.Count(); i++)
{
param[0] = dRow[i]["Campo 1"];
param[1] = dRow[i]["Campo 2"];
param[2] = dRow[i]["Campo 3"];
// Evito una excepción al hacer click en las cabeceras y si alguna celda tiene valor nulo
for (int j = 0; j < param.Length; j++)
if (param[j] == DBNull.Value)
param[j] = String.Empty;
dGridView.Rows.Add(param);
}
Todo bien hasta aquí. Pero sucedía que después de llamar a este código, en el control dGridView no se mostraban todas las filas añadidas, a menos que redimensionada el formulario contenedor. Peor aún, al recorrer las filas con las teclas de las flechas hacia arriba o abajo, me saltaba la siguiente excepción:
No se controló System.ArgumentOutOfRangeException
Message=El valor de '484' no es válido para 'Value'. 'Value' debería estar entre 'minimum' y 'maximum'.
Nombre del parámetro: Value
Source=System.Windows.Forms
ParamName=Value
StackTrace:
en System.Windows.Forms.ScrollBar.set_Value(Int32 value)
en System.Windows.Forms.DataGridView.ScrollRows(Int32 rowCount, Int32 deltaY, ScrollEventType scrollEventType)
Rebuscando en Internet, este blog me dio la solución.
Y era muy simple: Después de llenar el DataGridView se debe llamar al método PerformLayout de la siguiente manera:
dGridView.PerformLayout();
No he podido encontrar porqué esta función evita la excepción, ni siquiera en la web de Microsoft.
Update!!
El código de ejemplo aún tiene un error: el DataGridView dGridView aún puede tirar una excepción si hacemos clic a la cabecera de una columna que espera recibir datos numéricos. El código corregido es:
DataRow[] dRow = MetodoQueDevuelveUnArrayDeDataRows();
object[] param = new object[3];
// Los valores del sgte array deben coincidir con los nombres de las columnas
string[] columnas = { "Campo 1", "Campo 2", "Campo 3" };
for (int i = 0; i < dRow.Count(); i++)
{
param[0] = dRow[i]["Campo 1"];
param[1] = dRow[i]["Campo 2"];
param[2] = dRow[i]["Campo 3"];
// Evito una excepción al hacer click en las cabeceras y si alguna celda tiene valor nulo
for (int j = 0; j < param.Length; j++)
if (param[j] == DBNull.Value)
{
// en el caso de trabajar directamente con un Datatable la sgte línea se reemplaza por:
// if (unDataTable.Columns[columnas[j]].DataType == typeof(string))
if (dRow[i].Table.Columns[columnas[j]].DataType == typeof(string))
param[j] = String.Empty;
else
param[j] = 0;
}
dGridView.Rows.Add(param);
}
dGridView.PerformLayout();
DataRow[] dRow = MetodoQueDevuelveUnArrayDeDataRows();
object[] param = new object[3];
for (int i = 0; i < dRow.Count(); i++)
{
param[0] = dRow[i]["Campo 1"];
param[1] = dRow[i]["Campo 2"];
param[2] = dRow[i]["Campo 3"];
// Evito una excepción al hacer click en las cabeceras y si alguna celda tiene valor nulo
for (int j = 0; j < param.Length; j++)
if (param[j] == DBNull.Value)
param[j] = String.Empty;
dGridView.Rows.Add(param);
}
Todo bien hasta aquí. Pero sucedía que después de llamar a este código, en el control dGridView no se mostraban todas las filas añadidas, a menos que redimensionada el formulario contenedor. Peor aún, al recorrer las filas con las teclas de las flechas hacia arriba o abajo, me saltaba la siguiente excepción:
No se controló System.ArgumentOutOfRangeException
Message=El valor de '484' no es válido para 'Value'. 'Value' debería estar entre 'minimum' y 'maximum'.
Nombre del parámetro: Value
Source=System.Windows.Forms
ParamName=Value
StackTrace:
en System.Windows.Forms.ScrollBar.set_Value(Int32 value)
en System.Windows.Forms.DataGridView.ScrollRows(Int32 rowCount, Int32 deltaY, ScrollEventType scrollEventType)
Rebuscando en Internet, este blog me dio la solución.
Y era muy simple: Después de llenar el DataGridView se debe llamar al método PerformLayout de la siguiente manera:
dGridView.PerformLayout();
No he podido encontrar porqué esta función evita la excepción, ni siquiera en la web de Microsoft.
Update!!
El código de ejemplo aún tiene un error: el DataGridView dGridView aún puede tirar una excepción si hacemos clic a la cabecera de una columna que espera recibir datos numéricos. El código corregido es:
DataRow[] dRow = MetodoQueDevuelveUnArrayDeDataRows();
object[] param = new object[3];
// Los valores del sgte array deben coincidir con los nombres de las columnas
string[] columnas = { "Campo 1", "Campo 2", "Campo 3" };
for (int i = 0; i < dRow.Count(); i++)
{
param[0] = dRow[i]["Campo 1"];
param[1] = dRow[i]["Campo 2"];
param[2] = dRow[i]["Campo 3"];
// Evito una excepción al hacer click en las cabeceras y si alguna celda tiene valor nulo
for (int j = 0; j < param.Length; j++)
if (param[j] == DBNull.Value)
{
// en el caso de trabajar directamente con un Datatable la sgte línea se reemplaza por:
// if (unDataTable.Columns[columnas[j]].DataType == typeof(string))
if (dRow[i].Table.Columns[columnas[j]].DataType == typeof(string))
param[j] = String.Empty;
else
param[j] = 0;
}
dGridView.Rows.Add(param);
}
dGridView.PerformLayout();
lunes, 14 de enero de 2013
C#: Propiedad Select de un Datatable. Un par de Detalles.
Tengo un Datatable llamado "DT" que contiene muchos datos organizados en dos campos: "Campo1" y Campo 2". Quiero filtrar aquellos datos que contengan valores nulos en "Campo1" y en "Campo 2".
El código fuente será:
DataRow[] dRow = DT.Select("Campo1 is Null and [Campo 2] is Null");
Para detectar campos con valores nulos, le mandamos una consulta con "is Null". Como "Campo 2" tiene un espacio en blanco, lo pongo entre corchetes.
Si tengo este método:
DataRow[] Method1(string filtro)
{
Datatable DT = metodoQueDevuelveUnDatatable();
return DT.Select(filtro);
}
lo llamaré así:
DataRow[] dRow = Method1("Campo1 is Null and [Campo 2] is Null");
¿Pero cómo hago si deseo que Method1 me devuelva todas las filas de DT, sin aplicar ningún filtro?
Escribo lo siguiente:
DataRow[] dRow = Method1(String.Empty);
Enviar un String.Empty a la propiedad Select de un Datatable es una forma de decirle que no queremos filtrar nada y también de eliminar cualquier filtro aplicado con anterioridad.
El código fuente será:
DataRow[] dRow = DT.Select("Campo1 is Null and [Campo 2] is Null");
Para detectar campos con valores nulos, le mandamos una consulta con "is Null". Como "Campo 2" tiene un espacio en blanco, lo pongo entre corchetes.
Si tengo este método:
DataRow[] Method1(string filtro)
{
Datatable DT = metodoQueDevuelveUnDatatable();
return DT.Select(filtro);
}
lo llamaré así:
DataRow[] dRow = Method1("Campo1 is Null and [Campo 2] is Null");
¿Pero cómo hago si deseo que Method1 me devuelva todas las filas de DT, sin aplicar ningún filtro?
Escribo lo siguiente:
DataRow[] dRow = Method1(String.Empty);
Enviar un String.Empty a la propiedad Select de un Datatable es una forma de decirle que no queremos filtrar nada y también de eliminar cualquier filtro aplicado con anterioridad.
viernes, 14 de diciembre de 2012
Aplicando Linq a un array de Estructuras (struct)
Tengo un struct (Estructura) como el que se muestra a continuación (el constructor dentro del struct me permite asignarle valores usando la palabra reservada new):
private struct misEjes
{
public int ejeX;
public int ejeY;
public misEjes(int x, int y)
{
ejeX = x;
ejeY = y;
}
};
Y luego creo un array del struct misEjes de la forma:
misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();
Usando Linq puedo no sólo declarar el array, si no también definir la cantidad de elementos e inicializarlos. Todo esto lo hace Enumerable.Repeat(). Como éste devuelve un IEnumerable, debo convertirlo con un ToArray(). Para este ejemplo, mi arrray tiene 10 elementos (sus índices van del 0 al 9).
Realizo varias operaciones con los elementos de mi array, y al final deseo quedarme con los que no están repetidos. Para ello hago:
ejes1 = ejes1.Distinct().ToArray();
El Distinct() devuelve todos los elementos que no se repiten. Independientemente los miembros (en este ejemplo ejeX y ejeY) de los elementos del array ejes1 pueden repetirse, pero el conjunto de los miembros de cada elemento de ejes1 (la pareja ejeX y ejeY) debe ser único.
El código completo es:
class Program
{
private struct misEjes
{
public int ejeX;
public int ejeY;
public misEjes(int x, int y)
{
ejeX = x;
ejeY = y;
}
};
static void Main(string[] args)
{
Random rnd = new Random(Convert.ToInt32(DateTime.Now.Millisecond));
misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();
ejes1 =
ejes1.Select(c=> new misEjes(rnd.Next(0, 4), rnd.Next(0, 3))).ToArray();
foreach (misEjes em in ejes1)
Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY));
Console.WriteLine(String.Empty);
ejes1 = ejes1.Distinct().ToArray();
foreach (misEjes em in ejes1)
Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY));
Console.Read();
}
}
El resultado es:
Las líneas antes del espacio son el array original, las que están después son el array luego de aplicar Distinct(). Nótese cómo las parejas ejeX y ejeY no se repiten.
private struct misEjes
{
public int ejeX;
public int ejeY;
public misEjes(int x, int y)
{
ejeX = x;
ejeY = y;
}
};
Y luego creo un array del struct misEjes de la forma:
misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();
Usando Linq puedo no sólo declarar el array, si no también definir la cantidad de elementos e inicializarlos. Todo esto lo hace Enumerable.Repeat(). Como éste devuelve un IEnumerable, debo convertirlo con un ToArray(). Para este ejemplo, mi arrray tiene 10 elementos (sus índices van del 0 al 9).
Realizo varias operaciones con los elementos de mi array, y al final deseo quedarme con los que no están repetidos. Para ello hago:
ejes1 = ejes1.Distinct().ToArray();
El Distinct() devuelve todos los elementos que no se repiten. Independientemente los miembros (en este ejemplo ejeX y ejeY) de los elementos del array ejes1 pueden repetirse, pero el conjunto de los miembros de cada elemento de ejes1 (la pareja ejeX y ejeY) debe ser único.
El código completo es:
class Program
{
private struct misEjes
{
public int ejeX;
public int ejeY;
public misEjes(int x, int y)
{
ejeX = x;
ejeY = y;
}
};
static void Main(string[] args)
{
Random rnd = new Random(Convert.ToInt32(DateTime.Now.Millisecond));
misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();
ejes1 =
ejes1.Select(c=> new misEjes(rnd.Next(0, 4), rnd.Next(0, 3))).ToArray();
foreach (misEjes em in ejes1)
Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY));
Console.WriteLine(String.Empty);
ejes1 = ejes1.Distinct().ToArray();
foreach (misEjes em in ejes1)
Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY));
Console.Read();
}
}
El resultado es:
Las líneas antes del espacio son el array original, las que están después son el array luego de aplicar Distinct(). Nótese cómo las parejas ejeX y ejeY no se repiten.
jueves, 29 de noviembre de 2012
Propiedad Select de un DataTable y Error al añadir un DataRow: ArgumentException Esta fila ya pertenece a otra tabla
Tengo un DataTable llamado dt1 que contiene muchos datos. Entre esos datos hay dos columnas llamadas "Nombre y Apellido" y "Edad". Deseo poner en otro DataTable los datos de todas las personas mayores de 18 años y que no sean Juan Perez ó Juan Pérez.
Los DataTables tienen una propiedad Select que acepta consultas tipo SQL para filtrar datos en función a los nombres de sus columnas. Si estos nombres contienen espacios se deben poner entre corchetes.
El código es el siguiente:
string query = @"([Nombre y Apellido] <> 'Juan Perez' or
[Nombre y Apellido] <> 'Juan Pérez') and Edad > 18";
DataTable dtFin = new DataTable();
DataRow[] miFiltro = dt1.Select(query);
if (miFiltro.Length > 0)
{
// primero añado las columnas con su respectivo nombre
for (int i = 0; i < miFiltro[0].Table.Columns.Count; i++)
dtFin.Columns.Add(miFiltro[0].Table.Columns[i].ColumnName);
// añado las filas
for (int i = 0; i < miFiltro.Count(); i++)
dtFin.Rows.Add(miFiltro[i]);
}
Pero al correr este código me tiraba una exceción del tipo "ArgumentException Esta fila ya pertenece a otra tabla".
Buscando en Internet, Pedro Hurtado me dió la solución. (yo no hice la pregunta, pero que es la solución, lo es :D)
El código correcto es:
string query = @"([Nombre y Apellido] <> 'Juan Perez' or
[Nombre y Apellido] <> 'Juan Pérez') and Edad > 18";
DataTable dtFin = new DataTable();
DataRow[] miFiltro = dt1.Select(query);
if (miFiltro.Length > 0)
{
// primero añado las columnas con su respectivo nombre
for (int i = 0; i < miFiltro[0].Table.Columns.Count; i++)
dtFin.Columns.Add(miFiltro[0].Table.Columns[i].ColumnName);
// añado las filas
for (int i = 0; i < miFiltro.Count(); i++)
dtFin.Rows.Add(miFiltro[i].ItemArray);
}
Faltaba ponerle la propiedad ItemArray al añadir los DataRows de miFiltro al DataTable dtFin.
Los DataTables tienen una propiedad Select que acepta consultas tipo SQL para filtrar datos en función a los nombres de sus columnas. Si estos nombres contienen espacios se deben poner entre corchetes.
El código es el siguiente:
string query = @"([Nombre y Apellido] <> 'Juan Perez' or
[Nombre y Apellido] <> 'Juan Pérez') and Edad > 18";
DataTable dtFin = new DataTable();
DataRow[] miFiltro = dt1.Select(query);
if (miFiltro.Length > 0)
{
// primero añado las columnas con su respectivo nombre
for (int i = 0; i < miFiltro[0].Table.Columns.Count; i++)
dtFin.Columns.Add(miFiltro[0].Table.Columns[i].ColumnName);
// añado las filas
for (int i = 0; i < miFiltro.Count(); i++)
dtFin.Rows.Add(miFiltro[i]);
}
Pero al correr este código me tiraba una exceción del tipo "ArgumentException Esta fila ya pertenece a otra tabla".
Buscando en Internet, Pedro Hurtado me dió la solución. (yo no hice la pregunta, pero que es la solución, lo es :D)
El código correcto es:
string query = @"([Nombre y Apellido] <> 'Juan Perez' or
[Nombre y Apellido] <> 'Juan Pérez') and Edad > 18";
DataTable dtFin = new DataTable();
DataRow[] miFiltro = dt1.Select(query);
if (miFiltro.Length > 0)
{
// primero añado las columnas con su respectivo nombre
for (int i = 0; i < miFiltro[0].Table.Columns.Count; i++)
dtFin.Columns.Add(miFiltro[0].Table.Columns[i].ColumnName);
// añado las filas
for (int i = 0; i < miFiltro.Count(); i++)
dtFin.Rows.Add(miFiltro[i].ItemArray);
}
Faltaba ponerle la propiedad ItemArray al añadir los DataRows de miFiltro al DataTable dtFin.
sábado, 17 de noviembre de 2012
Convertir los datos en la propiedad DataSource de un DataGridView en un DataTable
Se pueden convertir, ó pasar, los datos almacenados en la propiedad DataSource de un DataGridView a un DataTable con el siguiente código:
Este código no funciona para casos en que los datos se añadieron al DataGridView con el método "Add" de las propiedades "Rows" y "Columns", dado que éstas no modifican a la propiedad "DataSource".
Por ejemplo, en el siguiente código:
El DataGridView se ve así:
Pero el DataTable "dt" es nulo, pues la propiedad "DataSource" no tiene ningún valor asignado.
DataTable dt = (DataTable)miDataGridView.DataSource;
Este código no funciona para casos en que los datos se añadieron al DataGridView con el método "Add" de las propiedades "Rows" y "Columns", dado que éstas no modifican a la propiedad "DataSource".
Por ejemplo, en el siguiente código:
miDataGridView.DataSource = null;
miDataGridView.Columns.Add("p1", "Prueba 1");
miDataGridView.Columns.Add("p2", "Prueba 2");
object[] obj = {"p1", "p2"};
miDataGridView.Rows.Add(obj);
DataTable dt = (DataTable)miDataGridView.DataSource;
miDataGridView.Columns.Add("p2", "Prueba 2");
object[] obj = {"p1", "p2"};
miDataGridView.Rows.Add(obj);
DataTable dt = (DataTable)miDataGridView.DataSource;
El DataGridView se ve así:
Pero el DataTable "dt" es nulo, pues la propiedad "DataSource" no tiene ningún valor asignado.
Suscribirse a:
Entradas (Atom)


