wolfran_hack
22-06-2015, 05:47:54
Hola a todos, estoy creando un pequeño soft que tiene una lista con varios datos de alumnos, estos datos se van modificando y creo un archivo especial ejemplo "NombredelArchivo.XXX" donde voy guardando los cambios y lo uso como base de datos temporal del programa, el problema que estoy teniendo es el siguiente:
tengo varios botones, uno para agregar un nuevo alumno, otro para editar una linea, otro para eliminar y otro para cambiar un valor y colorear una linea de la lista. Entonces utilizo el siguiente codigo para en cada cambio guardar en el fichero el registro nuevo:
procedure TForm1.SaveListViewToFile(AListView: TListView; sFileName: string);
var
idxItem, idxSub, IdxImage: Integer;
F: TFileStream;
pText: PChar;
sText: string;
W, ItemCount, SubCount: Word;
MySignature: array [0..2] of Char;
begin
// Inicio
with ListView1 do
begin
ItemCount := 0;
SubCount := 0;
//****
MySignature := 'LVF';
// ListViewFile
F := TFileStream.Create('NombredelArchivo.XXX', fmCreate or fmOpenWrite);
F.Write(MySignature, SizeOf(MySignature));
if Items.Count = 0 then
// List is empty
ItemCount := 0
else
ItemCount := Items.Count;
F.Write(ItemCount, SizeOf(ItemCount));
if Items.Count > 0 then
begin
for idxItem := 1 to ItemCount do
begin
with Items[idxItem - 1] do
begin
// Guardamos los SubItems
if SubItems.Count = 0 then
SubCount := 0
else
SubCount := Subitems.Count;
F.Write(SubCount, SizeOf(SubCount));
// Guardamos el Index
IdxImage := ImageIndex;
F.Write(IdxImage, SizeOf(IdxImage));
// Guardamos la Caption
sText := Caption;
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
F.Write(w, SizeOf(w));
F.Write(pText^, w);
StrDispose(pText);
if SubCount > 0 then
begin
for idxSub := 0 to SubItems.Count - 1 do
begin
// Guardamos los Items y SubItems
sText := SubItems[idxSub];
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
F.Write(w, SizeOf(w));
F.Write(pText^, w);
StrDispose(pText);
end;
end;
end;
end;
end;
F.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Guardamos los items
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
end;
Con esto esta perfecto y funciona en todos los botones, ahora agregue varias opciones para cargar en la lista como, cargar archivo csv, xml, etc... código:
procedure ListViewFromCSV(
theListView: TListView;
const FileName: String);
var item: TListItem;
index,
comPos,
subIndex: Integer;
theFile: TStringList;
Line: String;
begin
theFile := TStringList.Create;
theFile.LoadFromFile(FileName);
for index := 0 to theFile.Count -1 do begin
Line := theFile[index];
item := theListView.Items.Add;
comPos := Pos(';', Line);
item.Caption := Copy(Line, 1, comPos -1);
Delete(Line, 1, comPos);
comPos := Pos(';', Line);
while comPos > 0 do begin
item.SubItems.Add(Copy(Line, 1, comPos -1));
Delete(Line, 1, comPos);
comPos := Pos(';', Line);
end;
item.SubItems.Add(Line);
end;
FreeAndNil(theFile);
end;
OpenDialog1.Title := 'Importar Archivo *.CSV';
OpenDialog1.InitialDir := GetCurrentDir;
OpenDialog1.Filter := 'CSV (Formato de texto separado por comas) (*.csv)|*.csv';
OpenDialog1.DefaultExt := 'csv';
// Limpiamos por completo la Lista.
ListView1.Clear;
// Se abre un dialogo para abrir un archivo *.CSV
if OpenDialog1.Execute then
begin
ListViewFromCSV(ListView1, OpenDialog1.FileName);
perfecto, se cargar el archivo todo sin problemas. Ahora el problema esta en que luego de este código coloque el:
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
y no se guarda, y luego de esto los botones tampoco guardar nada en el NombredelArchivo.XXX, tampoco recibo ningún error, también probé de colocar el código directo:
procedure TForm1.CargarArchivoCSV1Click(Sender: TObject);
var
idxItem, idxSub, IdxImage: Integer;
Fe: TFileStream;
pText: PChar;
sText: string;
//sFileName: string;
W, ItemCount, SubCount: Word;
MySignature: array [0..2] of Char;
begin
OpenDialog1.Title := 'Importar Archivo *.CSV';
OpenDialog1.InitialDir := GetCurrentDir;
OpenDialog1.Filter := 'CSV (Formato de texto separado por comas) (*.csv)|*.csv';
OpenDialog1.DefaultExt := 'csv';
// Limpiamos por completo la Lista.
ListView1.Clear;
// Se abre un dialogo para abrir un archivo *.CSV
if OpenDialog1.Execute then
begin
ListViewFromCSV(ListView1, OpenDialog1.FileName);
//Initialization
with ListView1 do
begin
ItemCount := 0;
SubCount := 0;
//****
MySignature := 'LVF';
// ListViewFile
Fe := TFileStream.Create('NombredelArchivo.XXX', fmCreate or fmOpenWrite);
Fe.Write(MySignature, SizeOf(MySignature));
if Items.Count = 0 then
// List is empty
ItemCount := 0
else
ItemCount := Items.Count;
Fe.Write(ItemCount, SizeOf(ItemCount));
if Items.Count > 0 then
begin
for idxItem := 1 to ItemCount do
begin
with Items[idxItem - 1] do
begin
//Save subitems count
if SubItems.Count = 0 then
SubCount := 0
else
SubCount := Subitems.Count;
Fe.Write(SubCount, SizeOf(SubCount));
//Save ImageIndex
IdxImage := ImageIndex;
Fe.Write(IdxImage, SizeOf(IdxImage));
//Save Caption
sText := Caption;
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
Fe.Write(w, SizeOf(w));
Fe.Write(pText^, w);
StrDispose(pText);
if SubCount > 0 then
begin
for idxSub := 0 to SubItems.Count - 1 do
begin
//Save Item's subitems
sText := SubItems[idxSub];
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
Fe.Write(w, SizeOf(w));
Fe.Write(pText^, w);
StrDispose(pText);
end;
end;
end;
end;
end;
Fe.Free;
end;
end;
end;
luego deje todo como estaba pero sin guardar, que solo cargue el archivo y cree un FormOnCloseQuery y pense que si después de hacer varios cambios, cierro el programa y se guardaría el archivo con los datos:
procedure TForm1.FormOnCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
canClose:=False;
if Application.MessageBox('¿Desea salir?','Atención',mb_OkCancel + mb_IconQuestion)= idOk then begin
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
canClose:=True;
end
else begin
canClose := False;
end;
end;
Pero no, tampoco se guardan, ni recibo ningún error, por ende estoy mareado y sin saber que hacer, ahora cierro el programa y lo abro nuevamente y los botones guardar la info cargada o modificada, pero si pruebo de agregar un archivo, nada. Lo que creo es lo siguiente, que por algún motivo el archivo en algún caso no se cierra al momento de cárgalo y como el programa quiere reescribir el archivo no puede porque ya esta abierto en otro proceso interno.. o algo así. Ustedes que opinan?
tengo varios botones, uno para agregar un nuevo alumno, otro para editar una linea, otro para eliminar y otro para cambiar un valor y colorear una linea de la lista. Entonces utilizo el siguiente codigo para en cada cambio guardar en el fichero el registro nuevo:
procedure TForm1.SaveListViewToFile(AListView: TListView; sFileName: string);
var
idxItem, idxSub, IdxImage: Integer;
F: TFileStream;
pText: PChar;
sText: string;
W, ItemCount, SubCount: Word;
MySignature: array [0..2] of Char;
begin
// Inicio
with ListView1 do
begin
ItemCount := 0;
SubCount := 0;
//****
MySignature := 'LVF';
// ListViewFile
F := TFileStream.Create('NombredelArchivo.XXX', fmCreate or fmOpenWrite);
F.Write(MySignature, SizeOf(MySignature));
if Items.Count = 0 then
// List is empty
ItemCount := 0
else
ItemCount := Items.Count;
F.Write(ItemCount, SizeOf(ItemCount));
if Items.Count > 0 then
begin
for idxItem := 1 to ItemCount do
begin
with Items[idxItem - 1] do
begin
// Guardamos los SubItems
if SubItems.Count = 0 then
SubCount := 0
else
SubCount := Subitems.Count;
F.Write(SubCount, SizeOf(SubCount));
// Guardamos el Index
IdxImage := ImageIndex;
F.Write(IdxImage, SizeOf(IdxImage));
// Guardamos la Caption
sText := Caption;
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
F.Write(w, SizeOf(w));
F.Write(pText^, w);
StrDispose(pText);
if SubCount > 0 then
begin
for idxSub := 0 to SubItems.Count - 1 do
begin
// Guardamos los Items y SubItems
sText := SubItems[idxSub];
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
F.Write(w, SizeOf(w));
F.Write(pText^, w);
StrDispose(pText);
end;
end;
end;
end;
end;
F.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Guardamos los items
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
end;
Con esto esta perfecto y funciona en todos los botones, ahora agregue varias opciones para cargar en la lista como, cargar archivo csv, xml, etc... código:
procedure ListViewFromCSV(
theListView: TListView;
const FileName: String);
var item: TListItem;
index,
comPos,
subIndex: Integer;
theFile: TStringList;
Line: String;
begin
theFile := TStringList.Create;
theFile.LoadFromFile(FileName);
for index := 0 to theFile.Count -1 do begin
Line := theFile[index];
item := theListView.Items.Add;
comPos := Pos(';', Line);
item.Caption := Copy(Line, 1, comPos -1);
Delete(Line, 1, comPos);
comPos := Pos(';', Line);
while comPos > 0 do begin
item.SubItems.Add(Copy(Line, 1, comPos -1));
Delete(Line, 1, comPos);
comPos := Pos(';', Line);
end;
item.SubItems.Add(Line);
end;
FreeAndNil(theFile);
end;
OpenDialog1.Title := 'Importar Archivo *.CSV';
OpenDialog1.InitialDir := GetCurrentDir;
OpenDialog1.Filter := 'CSV (Formato de texto separado por comas) (*.csv)|*.csv';
OpenDialog1.DefaultExt := 'csv';
// Limpiamos por completo la Lista.
ListView1.Clear;
// Se abre un dialogo para abrir un archivo *.CSV
if OpenDialog1.Execute then
begin
ListViewFromCSV(ListView1, OpenDialog1.FileName);
perfecto, se cargar el archivo todo sin problemas. Ahora el problema esta en que luego de este código coloque el:
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
y no se guarda, y luego de esto los botones tampoco guardar nada en el NombredelArchivo.XXX, tampoco recibo ningún error, también probé de colocar el código directo:
procedure TForm1.CargarArchivoCSV1Click(Sender: TObject);
var
idxItem, idxSub, IdxImage: Integer;
Fe: TFileStream;
pText: PChar;
sText: string;
//sFileName: string;
W, ItemCount, SubCount: Word;
MySignature: array [0..2] of Char;
begin
OpenDialog1.Title := 'Importar Archivo *.CSV';
OpenDialog1.InitialDir := GetCurrentDir;
OpenDialog1.Filter := 'CSV (Formato de texto separado por comas) (*.csv)|*.csv';
OpenDialog1.DefaultExt := 'csv';
// Limpiamos por completo la Lista.
ListView1.Clear;
// Se abre un dialogo para abrir un archivo *.CSV
if OpenDialog1.Execute then
begin
ListViewFromCSV(ListView1, OpenDialog1.FileName);
//Initialization
with ListView1 do
begin
ItemCount := 0;
SubCount := 0;
//****
MySignature := 'LVF';
// ListViewFile
Fe := TFileStream.Create('NombredelArchivo.XXX', fmCreate or fmOpenWrite);
Fe.Write(MySignature, SizeOf(MySignature));
if Items.Count = 0 then
// List is empty
ItemCount := 0
else
ItemCount := Items.Count;
Fe.Write(ItemCount, SizeOf(ItemCount));
if Items.Count > 0 then
begin
for idxItem := 1 to ItemCount do
begin
with Items[idxItem - 1] do
begin
//Save subitems count
if SubItems.Count = 0 then
SubCount := 0
else
SubCount := Subitems.Count;
Fe.Write(SubCount, SizeOf(SubCount));
//Save ImageIndex
IdxImage := ImageIndex;
Fe.Write(IdxImage, SizeOf(IdxImage));
//Save Caption
sText := Caption;
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
Fe.Write(w, SizeOf(w));
Fe.Write(pText^, w);
StrDispose(pText);
if SubCount > 0 then
begin
for idxSub := 0 to SubItems.Count - 1 do
begin
//Save Item's subitems
sText := SubItems[idxSub];
w := Length(sText);
pText := StrAlloc(Length(sText) + 1);
StrPLCopy(pText, sText, Length(sText));
Fe.Write(w, SizeOf(w));
Fe.Write(pText^, w);
StrDispose(pText);
end;
end;
end;
end;
end;
Fe.Free;
end;
end;
end;
luego deje todo como estaba pero sin guardar, que solo cargue el archivo y cree un FormOnCloseQuery y pense que si después de hacer varios cambios, cierro el programa y se guardaría el archivo con los datos:
procedure TForm1.FormOnCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
canClose:=False;
if Application.MessageBox('¿Desea salir?','Atención',mb_OkCancel + mb_IconQuestion)= idOk then begin
SaveListViewToFile(ListView1, 'NombredelArchivo.XXX');
canClose:=True;
end
else begin
canClose := False;
end;
end;
Pero no, tampoco se guardan, ni recibo ningún error, por ende estoy mareado y sin saber que hacer, ahora cierro el programa y lo abro nuevamente y los botones guardar la info cargada o modificada, pero si pruebo de agregar un archivo, nada. Lo que creo es lo siguiente, que por algún motivo el archivo en algún caso no se cierra al momento de cárgalo y como el programa quiere reescribir el archivo no puede porque ya esta abierto en otro proceso interno.. o algo así. Ustedes que opinan?