troubleshooting Question

How to load and save listview content

Avatar of Peter Kiers
Peter KiersFlag for Netherlands asked on
Delphi
6 Comments1 Solution491 ViewsLast Modified:
Hi,

I am using a working code to load and save the content of a listview.
Until Espasquier came with a more sufisticated code. That I want to
use but can read!

Can someone please help me to adjust the code of Espasquier
with the settings I use in my code:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  if FileExists('Data1\Glucose.sav') then LoadListViewToFile(lstvGlucose, 'Data1\Glucose.sav');
  if FileExists('Data1\Bolus.sav') then LoadListViewToFile(lstvBolus, 'Data1\Bolus.sav');
  if FileExists('Data1\FoodDB.sav') then LoadListViewToFile(lstvFoodDB, 'Data1\FoodDB.sav');
  if FileExists('Data1\OwnDB.sav') then LoadListViewToFile(lstvOwnDB, 'Data1\OwnDB.sav');
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SaveListViewToFile(lstvGlucose, 'Data1\Glucose.sav');
  SaveListViewToFile(lstvBolus, 'Data1\Bolus.sav');
  SaveListViewToFile(lstvFoodDB, 'Data1\FoodDB.sav');
  SaveListViewToFile(lstvOwnDB, 'Data1\OwnDB.sav');
end;

Thank you in advanced.

Peter



My code:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  if FileExists('Data1\Glucose.sav') then LoadListViewToFile(lstvGlucose, 'Data1\Glucose.sav');
  if FileExists('Data1\Bolus.sav') then LoadListViewToFile(lstvBolus, 'Data1\Bolus.sav');
  if FileExists('Data1\FoodDB.sav') then LoadListViewToFile(lstvFoodDB, 'Data1\FoodDB.sav');
  if FileExists('Data1\OwnDB.sav') then LoadListViewToFile(lstvOwnDB, 'Data1\OwnDB.sav');
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SaveListViewToFile(lstvGlucose, 'Data1\Glucose.sav');
  SaveListViewToFile(lstvBolus, 'Data1\Bolus.sav');
  SaveListViewToFile(lstvFoodDB, 'Data1\FoodDB.sav');
  SaveListViewToFile(lstvOwnDB, 'Data1\OwnDB.sav');
end;

procedure TMainForm.LoadListViewToFile(AListView: TListView; sFileName: string);
var
  F: TFileStream;
  IdxItem, IdxSubItem, IdxImage: Integer;
  W, ItemCount, SubCount: Word;
  pText: PChar;
  PTemp: PChar;
  MySignature: array [0..2] of Char;
  sExeName: string;
begin
  with AListView do
  begin
    ItemCount := 0;
    SubCount  := 0;
    sExeName := ExtractFileName(sFileName);
    if not FileExists(sFileName) then
    begin
      MessageBox(Handle, PChar(Format(Msg1, [sExeName])), 'I/O Error', MB_ICONERROR);
      Exit;
    end;
    F := TFileStream.Create(sFileName, fmOpenRead);
    F.Read(MySignature, SizeOf(MySignature));
    if MySignature <> 'LVF' then
    begin
      MessageBox(Handle, PChar(Format(Msg2, [sExeName])), 'I/O Error', MB_ICONERROR);
      Exit;
    end;
    F.Read(ItemCount, SizeOf(ItemCount));
    Items.Clear;
    for idxItem := 1 to ItemCount do
    begin
      with Items.Add do
      begin
        F.Read(SubCount, SizeOf(SubCount));
        F.Read(IdxImage, SizeOf(IdxImage));
        ImageIndex := IdxImage;
        F.Read(w, SizeOf(w));
        pText := StrAlloc(w + 1);
        pTemp := StrAlloc(w + 1);
        F.Read(pTemp^, W);
        StrLCopy(pText, pTemp, W);
        Caption := StrPas(pText);
        StrDispose(pTemp);
        StrDispose(pText);
        if SubCount > 0 then
        begin
          for idxSubItem := 1 to SubCount do
          begin
            F.Read(w, SizeOf(w));
            pText := StrAlloc(w + 1);
            pTemp := StrAlloc(w + 1);
            F.Read(pTemp^, W);
            StrLCopy(pText, pTemp, W);
            Items[idxItem - 1].SubItems.Add(StrPas(pText));
            StrDispose(pTemp);
            StrDispose(pText);
          end;
        end;
      end;
    end;
    F.Free;
  end;
end;

procedure TMainForm.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
  with AListView do
  begin
    ItemCount := 0;
    SubCount  := 0;
    MySignature := 'LVF';
    F := TFileStream.Create(sFileName, fmCreate or fmOpenWrite);
    F.Write(MySignature, SizeOf(MySignature));
    if Items.Count = 0 then
      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
          if SubItems.Count = 0 then
            SubCount := 0
          else
            SubCount := Subitems.Count;
          F.Write(SubCount, SizeOf(SubCount));
          IdxImage := ImageIndex;
          F.Write(IdxImage, SizeOf(IdxImage));
          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
              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;

ESPASQUIER:

// GLOBAL STREAM UTILS : Load/Save Int/Strings

procedure StreamWriteInt(aStream:TStream;Val:Integer);
begin
 aStream.Write(Val,sizeof(Val)); 
end;

function  StreaReadInt(aStream:TStream):Integer;
begin
 aStream.Read(Result,sizeof(Result));
end; 

procedure StreamWriteString(aStream:TStream;aString:String);
Var
 L:Integer;
begin
 L:=Length(aString);
 StreamWriteInt(L);
 if L>0 Then aStream.Write(PChar(@aString[1])^,L*sizeof(Char));
end;
 
function StreamReadString(aStream:TStream):String;
Var
 L:Integer;
begin
 L:=StreaReadInt(aStream);
 SetLength(Result,L);
 if L>0 Then aStream.Read(PChar(@Result[1])^,L*sizeof(Char));
end;

//======== Load/Save ListView in stream ========

procedure StreamWriteListView(aStream:TStream;aListView:TListView);
Var
 i,j:integer;
begin
 StreamWriteInt(aStream,aListView.Items.Count);
 for i:=0 to aListView.Items.Count-1 do
  with aListView.Items[idxItem - 1] do
   begin
    StreamWriteString(aStream,Caption);
    StreamWriteInt(aStream,ImageIndex);
    StreamWriteInt(aStream,Subitems.Count);
    for j:=0 to Subitems.Count-1 do StreamWriteString(aStream,Subitems[j]);
   end;
end;

procedure StreamReadListView(aStream:TStream;aListView:TListView);
Var
 N,i,NS,j:integer;
begin
 aListView.Clear;
 N:=StreamReadInt(aStream);
 for i:=0 to N-1 do
  with aListView.Items.Add do
   begin
    Caption:=StreamReadString(aStream);
    ImageIndex:=StreamReadInt(aStream);
    NS:=StreamReadInt(aStream,Subitems.Count);
    for j:=0 to NS-1 do Subitems.Add(StreamReadString(aStream));
   end;
end;

//======== Load/Save ONE ListView in a file ========

procedure SaveListViewToFile(AListView: TListView; sFileName: string);
var
 F: TFileStream;
begin
 F := TFileStream.Create(sFileName, fmCreate or fmOpenWrite);
 try
  StreamWriteListView(F,AListView);
 finally
  F.Free;
 end;
end;

procedure LoadListViewToFile(AListView: TListView; sFileName: string);
var
 F: TFileStream;
begin
 F := TFileStream.Create(sFileName, fmOpenRead);
 try
  StreamReadListView(F,AListView);
 finally
  F.Free;
 end;
end;
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 6 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 6 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros