hola gente necesito hacer una importación de datos en una planilla excel desde un botón o con componentes desde ya gracias

#1
Posted 16 July 2018 - 11:42 AM
#2
Posted 16 July 2018 - 08:45 PM
Hay muchas formas de leer excel desde Delphi, desde cosas "artesanales", hasta componentes de terceros, de los cuales hay gratuitos y pagos
Una forma sencilla de hacerlo es acceder usando ADO. Yo me he creado una pequeña clase que me ayuda a trabajar con este enfoque. Basicamente te permite usar un archivo excel como si fuera un DataSet. Podes estudiar el codigo acá
Es cierto que para usar mi solucion hay que tener en cuenta algunas dependencias (como por ejemplo, el Spring4D Framework). Sino, podes estudiar el codigo fuente para ver como obtener los datos con ADO (que tambien es muy sencillo). En realidad esta solucion es algo mas complicada para alguna necesidad que tuve en algun momento
#3
Posted 17 July 2018 - 06:27 AM
Bueno. Te pongo una parte de un código que uso para ello. No depende de ningún componente de terceros. Por supuesto, está sujeto a todo tipo de modificaciones y comentarios.
procedure TfrmPrincipal.btnbuscarClick(Sender: TObject); var archivo:string; begin if dlgAbrir.Execute then begin archivo:=dlgAbrir.FileName; txtArchivo.Text:=archivo; end; end; procedure TfrmPrincipal.btndatosgrillaClick(Sender: TObject); var excel, hoja:Variant; i:integer; PrimeraFila, UltimaFila, CantidadFilas, FilaExcel:Integer; begin if campoCompleto(txtPrimeraFila.Text) and campoCompleto(txtUltimaFila.Text) then begin grdNumeros.ClearRows; try excel:=CreateOleObject('excel.application'); excel.workbooks.open(txtArchivo.Text); hoja:=excel.Worksheets[StrToInt(txtNroHojaExcel.Text)]; PrimeraFila:=StrToInt(txtPrimeraFila.Text); UltimaFila:=StrToInt(txtUltimaFila.Text); //grdNumeros.AddRow(UltimaFila - PrimeraFila + 1); CantidadFilas:=UltimaFila - PrimeraFila + 1; grdNumeros.RowCount:=CantidadFilas; gNumeros.MaxValue:=CantidadFilas; gNumeros.Progress:=0; with grdNumeros do begin BeginUpdate; for i:=0 to (CantidadFilas - 1) do begin FilaExcel:=PrimeraFila + i; CellByName['clNroCarton', i].AsInteger:=hoja.cells[FilaExcel, 1]; CellByName['clCombinacion', i].AsInteger:=hoja.cells[FilaExcel, 2]; //Los Números CellByName['clNro1', i].AsInteger:=hoja.cells[FilaExcel, 3]; CellByName['clNro2', i].AsInteger:=hoja.cells[FilaExcel, 4]; CellByName['clNro3', i].AsInteger:=hoja.cells[FilaExcel, 5]; CellByName['clNro4', i].AsInteger:=hoja.cells[FilaExcel, 6]; CellByName['clNro5', i].AsInteger:=hoja.cells[FilaExcel, 7]; CellByName['clNro6', i].AsInteger:=hoja.cells[FilaExcel, 8]; CellByName['clNro7', i].AsInteger:=hoja.cells[FilaExcel, 9]; CellByName['clNro8', i].AsInteger:=hoja.cells[FilaExcel, 10]; CellByName['clNro9', i].AsInteger:=hoja.cells[FilaExcel, 11]; CellByName['clNro10', i].AsInteger:=hoja.cells[FilaExcel, 12]; Application.ProcessMessages; gNumeros.Progress:=i + 1; //Application.ProcessMessages; end; //Eliminamos la Hoja de Excel en cuestión excel.quit; EndUpdate; CalculateFooter(); end; Application.MessageBox('Cartones cargados con éxito.', PWideChar(lblTitulo.Caption), MB_OK + MB_ICONINFORMATION); except on e:Exception do begin excel.quit; mErrores(e, 'Imposible cargar Cartones', lblTitulo.Caption); end; end end else begin Application.MessageBox('Debe poner la primera y última fila', PWideChar(lbltitulo.caption), mb_ok + mb_iconerror); txtPrimeraFila.SetFocus; end; end;
Esto usa la Grilla NextGrid, pero puede reemplazarse fácilmente por la tradicional StringGrid. En la ventana tengo un componente grilla, dos botones (uno para traer la planilla y otro para la carga de la grilla), un Progress para ver el procentaje, unas cajitas de texto para la primera y última fila de Excel que quiero leer y creo que nada mas.
Espero sirva.
Edited by santiago14, 17 July 2018 - 06:30 AM.
#4
Posted 17 July 2018 - 02:01 PM
Hay muchas formas de leer excel desde Delphi, desde cosas "artesanales", hasta componentes de terceros, de los cuales hay gratuitos y pagos
Una forma sencilla de hacerlo es acceder usando ADO. Yo me he creado una pequeña clase que me ayuda a trabajar con este enfoque. Basicamente te permite usar un archivo excel como si fuera un DataSet. Podes estudiar el codigo acá
Es cierto que para usar mi solucion hay que tener en cuenta algunas dependencias (como por ejemplo, el Spring4D Framework). Sino, podes estudiar el codigo fuente para ver como obtener los datos con ADO (que tambien es muy sencillo). En realidad esta solucion es algo mas complicada para alguna necesidad que tuve en algun momento
hola, gracias por responder que componentes gratuitos conoces que me puedas recomendar o en caso que tengas uno me lo puedas pasar
saludos
#5
Posted 17 July 2018 - 02:03 PM
Bueno. Te pongo una parte de un código que uso para ello. No depende de ningún componente de terceros. Por supuesto, está sujeto a todo tipo de modificaciones y comentarios.
delphi
procedure TfrmPrincipal.btnbuscarClick(Sender: TObject); var archivo:string; begin if dlgAbrir.Execute then begin archivo:=dlgAbrir.FileName; txtArchivo.Text:=archivo; end; end; procedure TfrmPrincipal.btndatosgrillaClick(Sender: TObject); var excel, hoja:Variant; i:integer; PrimeraFila, UltimaFila, CantidadFilas, FilaExcel:Integer; begin if campoCompleto(txtPrimeraFila.Text) and campoCompleto(txtUltimaFila.Text) then begin grdNumeros.ClearRows; try excel:=CreateOleObject('excel.application'); excel.workbooks.open(txtArchivo.Text); hoja:=excel.Worksheets[StrToInt(txtNroHojaExcel.Text)]; PrimeraFila:=StrToInt(txtPrimeraFila.Text); UltimaFila:=StrToInt(txtUltimaFila.Text); //grdNumeros.AddRow(UltimaFila - PrimeraFila + 1); CantidadFilas:=UltimaFila - PrimeraFila + 1; grdNumeros.RowCount:=CantidadFilas; gNumeros.MaxValue:=CantidadFilas; gNumeros.Progress:=0; with grdNumeros do begin BeginUpdate; for i:=0 to (CantidadFilas - 1) do begin FilaExcel:=PrimeraFila + i; CellByName['clNroCarton', i].AsInteger:=hoja.cells[FilaExcel, 1]; CellByName['clCombinacion', i].AsInteger:=hoja.cells[FilaExcel, 2]; //Los Números CellByName['clNro1', i].AsInteger:=hoja.cells[FilaExcel, 3]; CellByName['clNro2', i].AsInteger:=hoja.cells[FilaExcel, 4]; CellByName['clNro3', i].AsInteger:=hoja.cells[FilaExcel, 5]; CellByName['clNro4', i].AsInteger:=hoja.cells[FilaExcel, 6]; CellByName['clNro5', i].AsInteger:=hoja.cells[FilaExcel, 7]; CellByName['clNro6', i].AsInteger:=hoja.cells[FilaExcel, 8]; CellByName['clNro7', i].AsInteger:=hoja.cells[FilaExcel, 9]; CellByName['clNro8', i].AsInteger:=hoja.cells[FilaExcel, 10]; CellByName['clNro9', i].AsInteger:=hoja.cells[FilaExcel, 11]; CellByName['clNro10', i].AsInteger:=hoja.cells[FilaExcel, 12]; Application.ProcessMessages; gNumeros.Progress:=i + 1; //Application.ProcessMessages; end; //Eliminamos la Hoja de Excel en cuestión excel.quit; EndUpdate; CalculateFooter(); end; Application.MessageBox('Cartones cargados con éxito.', PWideChar(lblTitulo.Caption), MB_OK + MB_ICONINFORMATION); except on e:Exception do begin excel.quit; mErrores(e, 'Imposible cargar Cartones', lblTitulo.Caption); end; end end else begin Application.MessageBox('Debe poner la primera y última fila', PWideChar(lbltitulo.caption), mb_ok + mb_iconerror); txtPrimeraFila.SetFocus; end; end;
Esto usa la Grilla NextGrid, pero puede reemplazarse fácilmente por la tradicional StringGrid. En la ventana tengo un componente grilla, dos botones (uno para traer la planilla y otro para la carga de la grilla), un Progress para ver el procentaje, unas cajitas de texto para la primera y última fila de Excel que quiero leer y creo que nada mas.
Espero sirva.
hola, gracias por responder en mi caso estoy trabajando con un dbgrid ya que requiero pasar ciertos campos a otro formulario
saludos
#6
Posted 10 August 2018 - 04:57 PM
Bueno. Te pongo una parte de un código que uso para ello. No depende de ningún componente de terceros. Por supuesto, está sujeto a todo tipo de modificaciones y comentarios.
delphi
procedure TfrmPrincipal.btnbuscarClick(Sender: TObject); var archivo:string; begin if dlgAbrir.Execute then begin archivo:=dlgAbrir.FileName; txtArchivo.Text:=archivo; end; end; procedure TfrmPrincipal.btndatosgrillaClick(Sender: TObject); var excel, hoja:Variant; i:integer; PrimeraFila, UltimaFila, CantidadFilas, FilaExcel:Integer; begin if campoCompleto(txtPrimeraFila.Text) and campoCompleto(txtUltimaFila.Text) then begin grdNumeros.ClearRows; try excel:=CreateOleObject('excel.application'); excel.workbooks.open(txtArchivo.Text); hoja:=excel.Worksheets[StrToInt(txtNroHojaExcel.Text)]; PrimeraFila:=StrToInt(txtPrimeraFila.Text); UltimaFila:=StrToInt(txtUltimaFila.Text); //grdNumeros.AddRow(UltimaFila - PrimeraFila + 1); CantidadFilas:=UltimaFila - PrimeraFila + 1; grdNumeros.RowCount:=CantidadFilas; gNumeros.MaxValue:=CantidadFilas; gNumeros.Progress:=0; with grdNumeros do begin BeginUpdate; for i:=0 to (CantidadFilas - 1) do begin FilaExcel:=PrimeraFila + i; CellByName['clNroCarton', i].AsInteger:=hoja.cells[FilaExcel, 1]; CellByName['clCombinacion', i].AsInteger:=hoja.cells[FilaExcel, 2]; //Los Números CellByName['clNro1', i].AsInteger:=hoja.cells[FilaExcel, 3]; CellByName['clNro2', i].AsInteger:=hoja.cells[FilaExcel, 4]; CellByName['clNro3', i].AsInteger:=hoja.cells[FilaExcel, 5]; CellByName['clNro4', i].AsInteger:=hoja.cells[FilaExcel, 6]; CellByName['clNro5', i].AsInteger:=hoja.cells[FilaExcel, 7]; CellByName['clNro6', i].AsInteger:=hoja.cells[FilaExcel, 8]; CellByName['clNro7', i].AsInteger:=hoja.cells[FilaExcel, 9]; CellByName['clNro8', i].AsInteger:=hoja.cells[FilaExcel, 10]; CellByName['clNro9', i].AsInteger:=hoja.cells[FilaExcel, 11]; CellByName['clNro10', i].AsInteger:=hoja.cells[FilaExcel, 12]; Application.ProcessMessages; gNumeros.Progress:=i + 1; //Application.ProcessMessages; end; //Eliminamos la Hoja de Excel en cuestión excel.quit; EndUpdate; CalculateFooter(); end; Application.MessageBox('Cartones cargados con éxito.', PWideChar(lblTitulo.Caption), MB_OK + MB_ICONINFORMATION); except on e:Exception do begin excel.quit; mErrores(e, 'Imposible cargar Cartones', lblTitulo.Caption); end; end end else begin Application.MessageBox('Debe poner la primera y última fila', PWideChar(lbltitulo.caption), mb_ok + mb_iconerror); txtPrimeraFila.SetFocus; end; end;
Esto usa la Grilla NextGrid, pero puede reemplazarse fácilmente por la tradicional StringGrid. En la ventana tengo un componente grilla, dos botones (uno para traer la planilla y otro para la carga de la grilla), un Progress para ver el procentaje, unas cajitas de texto para la primera y última fila de Excel que quiero leer y creo que nada mas.
Espero sirva.
hola Santiago opte por tu opción, quería hacerte una consulta el lblTitulo y dlgAbrir a que hace referencia en la parte del diseño
saludos
#7
Posted 13 August 2018 - 08:14 AM
hola Santiago opte por tu opción, quería hacerte una consulta el lblTitulo y dlgAbrir a que hace referencia en la parte del diseño
saludos
Hola. La cosa es sencilla.
lblTitulo es un Label, que está en el formulario y dice algo así como: "Exportación desde Excel". Solamente cartelería.
dlgAbrir es el componente TOpenDialog, para poder buscar el archivo Excel en la computadora.
#8
Posted 14 August 2018 - 07:06 PM
Hola. La cosa es sencilla.
lblTitulo es un Label, que está en el formulario y dice algo así como: "Exportación desde Excel". Solamente cartelería.
dlgAbrir es el componente TOpenDialog, para poder buscar el archivo Excel en la computadora.
tengo otra duda a que hace referencia " campo completo " , el " grdNumeros" hace referencia a la grilla no? y el "gNumeros " al Progress ?
#9
Posted 15 August 2018 - 05:34 AM
tengo otra duda a que hace referencia " campo completo " , el " grdNumeros" hace referencia a la grilla no? y el "gNumeros " al Progress ?
function campoCompleto(codigo:string):boolean; overload; begin result := not (Trim(codigo) = ''); // if (trim(codigo) = '') then // result:=false //algun campo está incompleto // else // result:=true; //todos los campos están completos end;
grdNumeros es la NextGrid
gNumeros es un ProgressBar
#10
Posted 15 August 2018 - 06:09 PM
delphi
function campoCompleto(codigo:string):boolean; overload; begin result := not (Trim(codigo) = ''); // if (trim(codigo) = '') then // result:=false //algun campo está incompleto // else // result:=true; //todos los campos están completos end;
grdNumeros es la NextGrid
gNumeros es un ProgressBar
otra pregunta es con el "txtNroHojaExcel.Text " y con respecto a la importación solo es una lectura del archivo o hace la lectura y la información del archivo la guarda en la base de datos ?gracias saludos
#11
Posted 16 August 2018 - 06:02 AM
otra pregunta es con el "txtNroHojaExcel.Text " y con respecto a la importación solo es una lectura del archivo o hace la lectura y la información del archivo la guarda en la base de datos ?gracias saludos
txtNroHojaExcel.Text es simplemente una caja de texto donde se indica la Hoja de Excel de la que se quiere leer. Creo que la primera es la 0 (cero), la segunda la 1 (uno), y así... Con esto, puedo leer de cualquier hoja que tenga el Libro.
En este caso, solamente es una lectura del archivo y la pone en la grilla. No hay inserción de estos datos a una BBDD.
#12
Posted 16 August 2018 - 02:55 PM
txtNroHojaExcel.Text es simplemente una caja de texto donde se indica la Hoja de Excel de la que se quiere leer. Creo que la primera es la 0 (cero), la segunda la 1 (uno), y así... Con esto, puedo leer de cualquier hoja que tenga el Libro.
En este caso, solamente es una lectura del archivo y la pone en la grilla. No hay inserción de estos datos a una BBDD.
mi intención es que esos datos se guarden en la base de datos,como podría guardar el excel existen componentes para guardar información gracias saludos
#13
Posted 16 August 2018 - 03:57 PM
mi intención es que esos datos se guarden en la base de datos,como podría guardar el excel existen componentes para guardar información gracias saludos
Se puede.
Y dependerá de los componentes/suite que utilices para la conexión y acceso a la base de datos. El motor que utilices puede condicionar en parte a la elección de la suite. Por ejemplo, si empleas Firebird seguramente optases por emplear Zeos por ej, en lugar de ADO. Y si usas MS SQL Server lo más probable es que decantes por ADO.
Y ni siquiera hace falta que coloques el contenido del archivo Excel en una grilla (un StringGrid). Puedes hacer pase de forma directa: simplemente a medida que lees fila a fila ejecutas una instrucción SQL INSERT INTO tabla con el contenido leido de las columnas en cuestión. Ya tienes la parte que hace la "lectura" del archivo, lo que sigue es que uses un Query, le definas en su propiedad SQL la consulta INSERT y le pases por parámetros (es lo más recomendable) los datos que te interesa almacenar en la base de datos.
Ejemplos de como hacer INSERT INTO con diversos componentes sobran en DelphiAccess si es lo que te preocupa. Me animo a decir que la forma en como se hace esto es prácticamente idéntica en todas las suites. Lo que va a variar es si usas parámetros, ya que en ADO se los invoca por Parameters, mientras que en el resto de las suites por Params. Todas las suites tienen su componente "Query", y lo que puede variar de una a otra es el componente "Conexión" y/o de "Transacción" (este último no todas las suites lo tienen, por lo que hacen transacciones de forma implícita)
Ahora, si necesitas mostrar lo que tiene la planilla ahi si te entendería que recurras a un componente visual para ello. Pero como dije: si al final de toda esta "discusión" en este hilo era para únicamente insertar la data en una DB, me parece un gasto absolutamente inncesario pasarlo a un "contenedor" cuando puede evitarse.
Saludos,
#14
Posted 10 September 2018 - 07:10 AM
mi intención es que esos datos se guarden en la base de datos,como podría guardar el excel existen componentes para guardar información gracias saludos
Hola. Es bastante simple. He aquí una pequeña parte de un código:
procedure NuevoDetRemitoTransporte(qryRemito:TFDQuery; DetRemito:TDetRemitosTransporte); begin with qryRemito, DetRemito do begin Close; sql.Clear; sql.Add('Insert into det_remitos_transporte (cod_remito, renglon_remito, '); sql.Add('cod_existencia, Descripcion_existencia, cant_producto, cant_entregada, cant_devuelta_producto, '); sql.Add('estado_det_remito) '); sql.Add('Values (:cod_remito, :renglon_remito, '); sql.Add(':cod_existencia, :Descripcion, :cant_producto, :cant_entregada, :cant_devuelta_producto, '); sql.Add(':estado_remito) '); ParamByName('cod_remito').AsInteger:=cod_remito; ParamByName('renglon_remito').AsInteger:=renglon; ParamByName('cod_existencia').AsInteger:=cod_existencia; ParamByName('Descripcion').AsString:=Descripcion; ParamByName('cant_producto').AsFloat:=CantidadProducto; ParamByName('cant_entregada').AsFloat:=CantidadEntregada; ParamByName('cant_devuelta_producto').AsFloat:=CantidadDevuelta; ParamByName('estado_remito').AsString:=EstadoDetRemito; try ExecSQL(); except raise; end; end; end; procedure TfrmRemitoTransporte.NuevoDetalleRemito(CodRemito:Integer); var i:Integer; DetRemito:TDetRemitosTransporte; begin DetRemito.cod_remito:=CodRemito; for i:=0 to grdCargaTransportada.RowCount - 1 do begin DetRemito.renglon:=i; DetRemito.cod_existencia:=grdCargaTransportada.CellByName['clCodExistencia', i].AsInteger; DetRemito.Descripcion:=grdCargaTransportada.CellByName['clCargaTransportada', i].AsString; DetRemito.CantidadProducto:=grdCargaTransportada.CellByName['clCantidadTransportada', i].AsFloat; DetRemito.CantidadEntregada:=0; DetRemito.CantidadDevuelta:=0; DetRemito.ObsDetRemitoEntrega:=''; //Sirve para las observaciones al momento de la devolución de esta moto DetRemito.EstadoDetRemito:='ACTIVO'; try NuevoDetRemitoTransporte(DataModule1.qryRemitosTransporte, DetRemito); except raise; end; end; end; procedure TfrmRemitoTransporte.btnRemitoClick(Sender: TObject); var validaciones:Boolean; Remito:TRemitosTransporte; DetRemito:TDetRemitosTransporte; Remitente:TRemitente; Chofer:TDatosChofer; Vendedor:TVendedores; Transporte:TDatosTransporte; Destino:TDestino; FilaCarga:FilaGrilla; i:Integer; begin validaciones:=DatosValidosEncRemito and DatosValidosRemitente and DatosValidosChofer and DatosValidosTransporte and DatosValidosVendedor and DatosValidosDestino and CargaTransportadaValida(ObtenerMaximaCantidadMotosPermitida); if validaciones and (IDYES = Application.MessageBox('¿Confirma registración de nuevo Remito de Transporte?', PWideChar(self.Caption), MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2)) then begin Remito:=TomarDatosEncRemito; Remitente:=TomarDatosRemitente; Chofer:=TomarDatosChofer; Transporte:=TomarDatosTransporte; Vendedor:=TomarDatosVendedor; Destino:=TomarDatosDestino; //Nuevo Remito Transporte with DataModule1 do begin terminarTransaccion; transaccion.StartTransaction; try NuevoEncRemitoTransporte(qryRemitosTransporte, Remitente, Vendedor, Chofer, Transporte, Destino, Remito); remito.cod_remito:=qryRemitosTransporte.FieldByName('cod_remito').AsInteger; //self.AsignarCodRemito(Remito.cod_remito); //Detalle del remito Self.NuevoDetalleRemito(remito.cod_remito); transaccion.CommitRetaining; //Impresión self.ImpresionRemitoTransporte(Remitente.cod_remitente, remito.cod_remito, Chofer.cod_chofer, Transporte.cod_transporte); transaccion.Rollback; Application.MessageBox(PWideChar('Remito de Transporte registrado con éxito.'), PWideChar(self.Caption), MB_OK + MB_ICONINFORMATION); LimpiarRemitoTransporte; //chkConLineas.Enabled:=True; //btnImpresion.Enabled:=True; except on e:Exception do begin terminarTransaccion; mErrores(e, 'Imposible registrar Remito de Transporte solicitado.', self.Caption); end; end; end; end; end;
De todo ese código lo que interesa es:
NuevoDetRemitoTransporte: Insert hacia la BBDD. Esto es unitario, uno por renglón que tenga la grilla.
NuevoDetalleRemito: Un ciclo que va sacando los datos, fila por fila, de la grilla. En este caso los va poniendo en un Record para luego pasarlo al Insert.
Todos los demás métodos son para diversas cosas que hay que meter en otras tablas de la BBDD, pero que no vienen al caso aquí. Para sacar los datos de la grilla se usan métodos de esta grilla en particular (NextGrid), pero puede hacerse sin problemas en la TStringGrid con DetRemito.CantidadEntregada:=STrToInt(grilla.Cells[fila, columna]);
En el módulo principal (btnRemitoClick), se inicia y termina la transacción, puesto que puede ser medio larga según la cantidad de registros que haya que meter. También se gestiona el caso en que haya algún problema contra la BBDD.
Espero ayude.
#15
Posted 17 September 2018 - 03:11 AM
pude hacer la importación, gracias a todos por sus comentarios