How to append to an existing file using FireDAC - delphi

I would like to write to an existing .csv file not create a new one every time it runs. Here is the code I have so far.
with TFDBatchMoveDataSetReader.Create(FDBatchMove) do begin
DataSet:= Inventory.mInventoryCount;
Optimise:= False;
end;
with TFDBatchMoveTextWriter.Create(FDBatchMove) do
AssignFile(myFile, 'C:\Dataout.csv');
//FileName:= ExtractFilePath('C:\') + 'DataOut.csv';
Append(myfile);
FDBatchMove.Execute

You are not supposed to do writing by yourself. That's what the writer does for you. You need to just control the Mode property and the clear options of the Options option set of the TFDBatchMove to instruct the engine what the writer should do. From what you say it sounds like you are interested in the dmAlwaysInsert mode (which is default) and keeping poClearDest and poClearDestNoUndo options not included in the option set (which is default as well).
Or in other words, FireDAC will append data with no checks to the destination by default, hence the problem you've described could have happen by modifying some of the mentioned settings (or, you just misidentified the issue).

Related

How to treat non design component initialization errors?

For start, lets take an exemplification:
You create a new VCL application project in Delphi and put a TIBDataBase and type in the path and name of the database file with the extension .IB ok?
Now, If you you just put example.ib and leave the path behind, when you execute your application without Delphi, it will open the database normally if the .EXE is in the same path as the .IB but if you run your application from Delphi, it will raise an error because it can't find the database file, because Delphi changes the working directory.
Sometimes you want to leave the Active property of that component set to True while you are developing, and them set to False and change it during the start of the application, when you deliver to your client. All that because he/she may want to install in a different path and your application has to find the proper place of the database before open it.
The problem comes when you already delivered to your client and still make some changes everyday on the code. You then have to deploy at least once a day, and sometime you just forget to set that property back to False and when the client receives the update and tries to run it, he/she gets a not found database error.
The question is, how can I handle that error if this opening happens automatically when the component is loaded in memory and the activation of the database does not happens in my own code?
I do not think you are going to find a general solution to preventing run time exceptions from design time property settings without modifying the component or deriving a descendent.
For TIBDatabase, set the property AllowStreamedConnected to False. This stops TIBDataBase from automatically connecting to the database at run time when Connected is True at design time. TIBQuery using this TIBDatabase will not open even it is set Active at design time.
Some other database connection components have similar properties.
Regarding the database issue only: if I understand you correctly, my solution requires you to write an event handler for the 'BeforeConnect' event as shown below:
procedure TDM.SQLConnection1BeforeConnect(Sender: TObject);
var
dir: string;
begin
with TRegIniFile.create (regpath) do // I keep my database locations in the registry
begin // but you can use any method of getting the location
dir:= ReadString ('firebird', progname, '');
free
end;
with sqlconnection1 do
begin
close;
params.values['database']:= dir;
loginprompt:= false;
end;
end;
This way, you can have one location stored in your database for local use, but have different locations for different users.

Set file as modified using OTA

As we know Build compiles all used units and Compile compiles only changed used units. But when you are working with ifdefs and need to change it a lot of times you must Build the project a lot of times.
If you have to much libraries that you know that this IFDEF will not change the behavior, there is no reason to build this library again.
What I want to do discovery is a way to say to the IDE that some files was changed and call the Compile and not the Build.
How to get the units and every else I know, but some know how to set the unit as modified?
Tks
Couldn't find a why to solve my problem yet. I found a way to set it as modified the problem is that it doesn't force the IDE to build it as I thought it'll.
Some one know what checks is made to an archive be sent to compile ?
Solved in a simpler way. I just deleted the DCU of the file and ok, it'll compile it again. :D
http://paste.ideaslabs.com/show/KCB9cq2Z8c
Let us assume that what you want is to mark editor buffers modified. That assumes there is an editor buffer to modify, which in most cases, there isn't, for most items in your Project. Let's suppose that you ALWAYS have every file in your project open at all times, then perhaps you can tweak those open units, this way.
My thinking is that you would actually need not only to mark editor buffers modified, but also TOUCH all the files on disk that would need to be rebuilt because of the #define change.
To know which files are affected, you would need to read all the files. I think, that the odds of you doing this reliably, over and over again, and faster than just doing a BUILD are pretty slim.
But if you did decide to go for it, you need not only to modify buffer Modified flags, but also, for any other file in the current project group, or which is in a folder included in the search or library path, find any file which might be affected.
You can see perhaps that this is more complex than you first thought.
And, as far as OTA goes, here is IOTAEditor property, Modified, it is read only.
The OTA doesn't want you changing it:
IOTAEditor = interface(IUnknown)
['{F17A7BD0-E07D-11D1-AB0B-00C04FB16FB3}']
...
function GetModified: Boolean;
..
property Modified: Boolean read GetModified;
..
end;
But you could actually modify the buffer CONTENT itself, and that would set the flag.
Use IOTAEditorContent, get the content (IStream), modify it (add a space), then modify it again (take away the space). You have now set the dirty bit (call GetModified just for luck).
I found some sample code from JCL JclStackTraceViewerStackCodeUtils.pas that shows you how to read editor content using IOTAEditorContent:
function GetFileEditorContent(const AFileName: string): IStream;
var
I: Integer;
Module: IOTAModule;
EditorContent: IOTAEditorContent;
begin
Result := nil;
Module := (BorlandIDEServices as IOTAModuleServices).FindModule(AFileName);
if Assigned(Module) then
begin
for I := 0 to Module.ModuleFileCount - 1 do
if Supports(Module.ModuleFileEditors[I], IOTAEditorContent, EditorContent) then
begin
Result := EditorContent.Content;
Break;
end;
end;
end;
After re-reading your question, it seems to me you only want to mark open editor buffers as all changed, and then do a compile, for speed. So you might want to do this: Take the code above, get the IOTAEditorContent using Supports(), and tweak each one.
Update: Short and sweet version: Modifying the buffer isn't sufficient. Plus, you won't have buffers for the files you need to change, plus Touching the file on the disk doesn't do what you want. So no, you can't do exactly what you wanted to do. And even if you could somehow modify the compiler's ability to do Make-style dependency and modification checks, you would probably cause a lot of problems inside the IDE.
On IOTAModule70 = interface(IOTAModule50) I'll find MarkModified:
Description:
{ MarkModifed will mark this module as "modified" without actually indicating
why is it modified (which will cause internal file dates to remain constant).
This will force the IDE to ask to save this module when the user attempts
to close it. It will also clear the "discardability" of a new unnamed
module such as when File|New|Application is selected. }

Form Designer Save and Load

i made a simple form designer in delphi, drag and drop a button on the form and it draws it, but the thing is i cant save/load this project since i dunno how to, is there anyway that i could be abel to save it to .rc file and load it from there?
That depends how you programmed your form designer. In forms created in Delphi's designer all components (and subcomponents) are referenced from TForm.Components array property. All controls are also referenced in TForm.Controls array property (if you remove an container control, all it's subcontrols are destroyed too).
If you have followed that pattern, all you have to do is monitor additions to the TForm.Components array (maybe using an overriden TForm.Notification method) and using this data to build your persistent form's file.
The VCL contains methods for using its builtin DFM support. There is a sample in the Delphi 2009 documentation for ObjectBinaryToText; I guess this works for D7 too. And IIRC there already was a code fragment for ComponentToString in the D5 help - search for ObjectBinaryToText.
Delphi stores form layout in *.dfm file. You can use it's structure to save your projects. File is textual and readable by humans. It is not hard to parse file like that rading one line by one. If you need more help, ask for it.
You can use something like delphi .DFM. Counting all objects and then read their attributes and write them into a file. Example Code:
For i:0 To Form1.ComponentsCount-1 Do Begin
// Read Component Attributes And Write Them In Your Format
End;
If you just want to save the form you designed in your designer, use something like TFileStream to create the RC file when the user saves. You might be better off with your own file format for your forms, with the option to export as an RC file, as RC files arent really meant to useful for storing any design time info you may need.

Easiest way to find previous instance of an application

I have rewritten a VB6 application in Delphi. It should have only one instance running. How can I do this with minimum of code?
In VB6 we just have to use one single line of code
>
If App.PrevInstance Then
'Take some action
End If
On goggling I did find a solution but it is very length and we have to mess with .drp file.
I do not want to do that.
I want something simpler.
I have some code along the lines of:
var
AppMutex: THandle;
{ .... }
initialization
// Create the mutex
AppMutex := CreateMutex(nil, True, 'MY-APPLICATION-NAME');
if (AppMutex = 0) or (GetLastError = ERROR_ALREADY_EXISTS) then
begin
MessageDlg('My application is already running on this computer.'#13#10+
'You should close the other instance before starting a new one.',mtError,
[mbOK],0);
Halt;
end;
finalization
// Close the mutex
CloseHandle(AppMutex);
but I'm sure the answers in the thread that #mghie linked to are more helpful/richer features!
Edit: Note you can make this into a small unit in it's own right, then just use that unit in your project(s).
Note that in many cases, the user's expecation will be that launching the second instance results in the first instance being restored and brought to the foreground. Don't expect users to understand the difference between restoring a minimized/hidden app and launching from a shortcut or start menu.
In my experience one cannot decide in general wether an application my be started twice or not. It may be for instance perfectly valid to start the same application if it is started in another folder or under another user account or whatever. On the other hand it might be the case that two different applications may not run together if they are started in the same folder or so.
So besides the different approaches with mutexes and semaphores and handling race conditions, it is the wise selection of the mutex's or semaphore's name that handles the above combinations appropriately.
If an application may not run twice at all, take a GUID like name. You can even use the exe's filename if you can ignore that someone might rename it.
Restricting the one-time-start on a specific folder, you can take the exe path into account, but be aware that due to mappings different pathes may end up at the same exe.

Copy TClientDataSet contents with field configurations

I would like to copy a whole TClientDataSet instance into another so I can recover any changes made in the original one. I've tried to saveToStream, to copy the data property but in all cases I loose the fields configurations (displayLabel, size, etc.)
Is there a way to do what I'm trying?
Delphi will only stream published properties. You may need to tweak things a bit to get everything out & back correctly. See http://www.delphipages.com/news/detaildocs.cfm?ID=145 for an example of the hooks.
-- MarkusQ
This should work:
DestClientDataSet.Data := SrcClientDataSet.Data;
Did you try TClientdataset.Clonecursor ?

Resources