Showing posts with label database. Show all posts
Showing posts with label database. Show all posts

Monday, April 20, 2020

Delphi Tip of the Day - Export to CSV

This weekend I had a bunch of data inside a FireDAC FDMemtable and I wanted to play around with that data in Excel. So, the first thing I did was review which data formats Excel would accept.


That's excellent! Excel allows both importing from XML and JSON both of which can done using FDMemtable.SaveToFile method. ( SaveToFile documentation )

I created an XML file using the SaveToFile method and then tried to import that file into Excel.


That didn't go so well. Where's my data? I'm starting to feel that "I hate Delphi" thing happening again! Let's try JSON. So. I created a JSON file using the SaveToFile method and then tried importing into Excel. 

"I just want the data in Excel."



That didn't go so well either. I've imported text files hundreds of times into Excel and it just worked. I wasn't in the mood to figure out what was going on. I'll save that for another day. I just want the data in Excel. 

"I know CSV works. Let's find a solution."


I know that text or csv files import just fine into Excel so let's see how to create a CSV file using Delphi. A quick google search turned up exactly what I was looking for, a simple solution written by Uwe Rabbe six years ago. Thank you Uwe!


This works with any TDataSet descendent! And just like that I love Delphi again.




Enjoy - Semper Fi
Gunny Mike
https://zilchworks.com

Feedback is always appreciated!

Saturday, July 13, 2013

Add DBDemos to ElevatdDB Manager on Windows 7

It turns out that Windows 7 has issues with BDE Administrator. I found this out when I tried to migrated the DBDemos database to ElevateDB Manager. (ElevateDB Manager is to ElevateDB as SQL Management Studio is to SQL Server)

I got this very strange error...


PDOXUSRS.NET error
What the hell is PDOXUSRS.NET?

It's a file BDE uses to store Paradox user information. It turns out that the default location BDE uses for storing information is the root of Drive C: . Unfortunately, Windows 7 does not allow this behavior. This was one of those "I love Delphi, I hate Delphi" days. I hate spending six hours trying to figure out this kind of crap. Now that it's figured out... I love Delphi... go figure.

Here how to fix this error:

First and foremost the BDE Administrator (bdeadmin.exe) must be set to run in Compatibility mode for Windows XP (Service Pack 2). If you don't change the compatibility mode setting for this program it will sit and spin when you try to save the changes. At that point your only option is to kill it with Task Manager.

Step 1: Set bdeadmin.exe to run in compatibility mode with XP SP2



Step 2: Create a folder in the root of the C: Drive called BDEShare

Step 3: Run BDE Administrator and change the NET DIR setting to C:\BDEShare


Step 4: Right click on PARADOX and choose Apply
Step 5: Click OK
Step 6: Close the notification dialog
Step 7: Close BDE Adminstrator
Step 8: Follow the instructions in my original DBDemos post

Semper Fi,
Gunny Mike
end.

Sunday, May 6, 2012

How to get the DBDemos Database into ElevatdDB

There are several Delphi tutorials out there that use the DBDemos database that ships with Delphi. I tend to learn much better if I actually perform the tasks outlined in these tutorials rather than just reading or viewing them. However, I'd much rather perform these tasks using ElevateDB, since this is the database I have chosen for all my new applications.

I started looking around to see if someone has done this already. I was looking for a .zip file out there in internet land. I posted to the ElevateDB support group hoping someone had a .zip file I could get my hands on. What I found was much more valuable.

One of the regulars, Roy, said why don't you just use the "built-in BDE migrator" that comes with ElevateDB.
This is one of the coolest things I have done with ElevateDB. I learned so much more going through this process then I would have if I simply downloaded some .zip off the internet.This whole process takes less than 5 minutes from start to finish. It looks very complicated but believe me it's not.

Step 1 - Create a Session Called DBDemos

Make sure you have the ElevateDB Manager up and running. Right-Click on ElevateDB Manager and then choose Create New Session

General Tab

There are two things that need to be done inside the General tab.
  1. Name:  DBDemos
  2. Description:  DBDemos database that ships with Delphi
DO NOT CLICK OK . . Switch to the Local tab

Local Tab

There are two things that need to be done inside the Local tab.
  1. File Folder:  Enter the location for configuration file for this session. Don't worry if this folder doesn't exist, it will get created for you later on.
  2. Large File Support:  Make sure this box is checked.
DO NOT CLICK OK . . Switch to the Login tab



Login Tab


There are three things that need to be done inside the Login tab.
  1. User Name: Administrator
  2. Password: Enter:  EDBDefault

  3. Confirm Password:  EDBDefault
NOW CLICK OK


Click Yes if prompted to create folder.

Step 2 - Create Database Migrators

Now we need to add the database Migrators that come with ElevateDB to the DBMemos session.

  • Expand the ElevateDB Manager by clicking on the + (Plus)
  • You will see the DBDemos session we just created
  • Expand the DBDemos session by clicking on the + (Plus)
  • Right-Click on DBDemos
  • Choose Create Database Migrators


Step 3 - Create an Empty DBDemos database

Now we need to add the database Migrators that come with ElevateDB to the DBMemos session.


  • Expand the ElevateDB Manager by clicking on the + (Plus)
  • Expand the DBDemos session by clicking on the + (Plus)
  • Right-Click on Databases
  • Choose Create New Database...


There are three things that need to be done on the General tab
  1. Name:DBDemos
  2. Description: DBDemos Database that ships with Delphi

  3. Folder: Enter the location where you want the database files to reside. In my example I simply use a DB folder in the same location as the session folder.
CLICK OK WHEN DONE

Click OK when Done

Step 4 - Migrate the DBDemos Database and Into ElevateDB

 We are almost done, this is the final step.

  • Expand ElevateDB Manager by clicking on the + (Plus)
  • Expand DBDemos session by clicking on the + (Plus)
  • Expand Databases by clicking on the + (Plus)
  • Right-Click on DBDemos database
  • Choose Migrate Database...


There are seven things that need to be done on the Migrate Database Source tab.
  1. Migrator: Choose BDE
  2. Ckeckbox: Make sure Include Table Data is checked
  3. Parameters Grid: Click DatabaseName to highlight the grid row
  4. Value: Enter DBDemos
  5. Click Set Paramter Value button
  6. Veify the Parameter Grid shows DBDemos for the DatabaseName
  7.  Click OK
 

Congratulations. You now have an ElevatdDB version of the DBDemos database you can use to follow along with all the Delphi tutorials out there.

Enjoy!

Semper Fi - Gunny Mike

Monday, October 10, 2011

ElevateDB: Function isDate()

I am without a doubt spoiled by some of Microsoft SQL Server's built in functions. One such built in function that I have used many times is the isDATE function. This function let's you test whether a data value represents a date.

ElevateDB does not have an isDATE function, so I built one and will show you the process I went through to make one.

First I fired up the EDB Manager and created a new script that I could code and test as I went. I decided to see if I could use a BEGIN ... EXCEPTION ... END block to build this function. According to the documentation

Use these statements to declare a block of statements for execution in a procedure or function with an associated exception block of statements for handling any exceptions that may occur in the block of statements.

My intent was to "force an error" by trying to cast a string as a date and trap for an error if the string did not represent a date. It worked. The only gotcha was this, when I executed the code inside an EDB Manager script window, EDB Manager stopped execution to tell me that there was a conversion error with the line

SET TestDate = CAST(strDate as Date);

ElevateDB Error #1011 An error occurred with the value 12345678 (A conversion error occurred)

I will use the error number 1011 in the exception handling.

I fully expected an error to occur but I didn't know the error number ahead of time. I then clicked continue and the program stopped at the breakpoint I had set for SET X = 1; When I inspected the local variables, I saw that the script had done exactly what I asked. It set the isDATE value to 0 (meaning not a date). When I toggle between commenting one of the SET strDate = ... lines, the script perfoms correctly.

Copy this code into a new SCRIPT window inside EDB Manager and set a break point at the line
SET X = 1;.

Notice the second SET strDate statement has been commented out
--SET strDate = '1959-03-23'; commented out.

You can toggle between commenting out both of these SET strDate statements to see how EDB Manager handles good and bad date data.

SCRIPT
BEGIN
----------------------------------------------------------------
-- X is used set a breakpoint within ED Manager
----------------------------------------------------------------
DECLARE X INTEGER;

DECLARE strDate varchar(20);
DECLARE TestDate DATE;
DECLARE isDATE INTEGER;
DECLARE ErrCode Integer;

SET isDATE = 1;
SET strDate = '12345678';--SET strDate = '1959-03-23';
SET ErrCode = 0;

BEGIN
SET TestDate = CAST(strDate as Date);
EXCEPTION
   SET ErrCode = ERRORCODE();
   IF ERRORCODE()=1011 THEN
     SET isDATE = 0;
   END IF;
END;
SET X = 1;
END
Converting the above script into an actual function is pretty straight forward. From inside EDB Manager open a new SQL window and copy the following code:
br />
CREATE FUNCTION "isDate"  (INOUT "DateStr" VARCHAR(20) COLLATE UNI)
RETURNS INTEGER

BEGIN
DECLARE TestDate DATE;
DECLARE ValidDate INTEGER;

SET DateStr = COALESCE(DateStr,'');
SET ValidDate = 1;

BEGIN
SET TestDate = CAST(DateStr as Date);
EXCEPTION
   IF ERRORCODE()=1011 THEN
     SET ValidDate = 0;
   END IF;
END;

RETURN ValidDate;
END
This ElevateDB isDATE function is not as robust as the MS SQL Server function but it does allow you to test whether the date value passed in represents a date. Enjoy.

Semper Fi,
Gunny Mike

Wednesday, September 21, 2011

ElevatdDB: Date Math 2

Let me start off by mentioning a couple things. I'm not an expert at ElevateDB by any means and I don't claim to be one either. I purchased ElevateDB three weeks ago on 09/01/2011, and have only been using it for about ten days within that three week period.

I'm sharing my ElevateDB experiences with you as they are happening. So, I'm blogging about what I'm learning along the way. As I get more proficient with ElevateDB I hope to reflect that proficiency in my postings about ElevateDB.

Before I get to the Date Math stuff I need to tell you about the SQL query tool that comes with ElevateDB. It's called ElevateDB Manager. If you are familiar with Microsoft's SQL Server Management Studio or Microsoft's SQL Query Analyzer you should feel pretty comfortable with this tool. As of this writing it does not come with it's own manual. You can learn by doing or reading some of the support forum posts.

All the stuff I have been doing so far has been done from within a script window inside the the ElevateDB Manager. You open a new script window by clicking New|Script.











You can also set what are called "Breakpoints". Breakpoints do exactly what they sound like they do, they break in and stop execution of a script as a specific point. To set a break point within a script you click inside the grey margin next to the line where you want the script execution to stop.











Breakpoints are very cool. They let you see the current value of all the local variable that have been declared within the script at the very spot of the breakpoint. I set the breakpoint at the line
SET X = 1;
which is a do nothing statement purely for the purpose of letting me view the local variables.














I'm metioning these items because that is how I tested and viewed the results of the date math code I'm about to share with you.

How many times have you had to use a Start Date and End Date within your SQL queries? How many times have you had to set the Start Date equal to the first day of the current month and the End Date to the last day of the current month? How about the first and last days of the previous month, or the following month.

I'm about to show you a simple, sure fire way to set these dates so they work everytime, no matter what. You don't need to worry about going backwards or forwards a year. You don't need to worry whether there are 30 or 31 days in a month. You don't need to worry about February having 28 or 29 days. It's that simple.

Just copy and past this code into an ElevateDB Script. Set a breakpoint at the line mentioned above and your all set. There's only one line that needs to be inserted into the bottom two examples that makes them different from the first example. I've colored them red.

How to set the StartDate and EndDate for the Current Month


SCRIPT
BEGIN
----------------------------------------------------------------
-- This snippet of code sets the StartDate and EndDate to the 
-- first day  and last day of the current month
----------------------------------------------------------------
DECLARE Today     DATE;
DECLARE YYYY      INTEGER;
DECLARE MM        INTEGER;
DECLARE DateStr   VARCHAR(10);
DECLARE WorkDate  DATE;
DECLARE StartDate DATE;
DECLARE EndDate   DATE;

----------------------------------------------------------------
-- X is used set a breakpoint within ED Manager
----------------------------------------------------------------
DECLARE X INTEGER;

----------------------------------------------------------------
-- Get the current Year and Month
----------------------------------------------------------------
SET Today = Current_Date;
SET YYYY  = EXTRACT(YEAR FROM Today);
SET MM    = EXTRACT(Month FROM Today);

----------------------------------------------------------------
-- Set the WorkDate equal to the first day of the current month
-- by building a date string from the extracted date parts
-- Example: YYYY-MM-01
-- WHERE YYYY is the extracted Year
-- AND   MM   is the extracted Month
-- Make sure to pad any month less than 10 with a leading zero
----------------------------------------------------------------
SET DateStr = '';
SET DateStr = DateStr + CAST(YYYY as VARCHAR);
SET DateStr = DateStr + '-';
IF MM < 10 THEN
  SET DateStr = DateStr + '0';
END IF;
SET DateStr = DateStr + CAST(MM as VARCHAR);
SET DateStr = DateStr + '-01';
SET WorkDate  = CAST(DateStr as DATE);

----------------------------------------------------------------
-- Set StartDate equal to the first day of the month and create
-- the EndDate by performing two simple date math operations
-- 1. Add one Month to the WorkDate
-- 2. Subtract one Day from the WorkDate
----------------------------------------------------------------
SET StartDate = WorkDate;
SET WorkDate  = WorkDate + Interval  '1' MONTH;
SET WorkDate  = WorkDate + Interval '-1' DAY;
SET EndDate   = WorkDate;

SET X = 1;
END

How to set the StartDate and EndDate for the Previous Month


SCRIPT
BEGIN
----------------------------------------------------------------
-- This snippet of code sets the StartDate and EndDate to the 
-- first day  and last day of the previous month
----------------------------------------------------------------
DECLARE Today     DATE;
DECLARE YYYY      INTEGER;
DECLARE MM        INTEGER;
DECLARE DateStr   VARCHAR(10);
DECLARE WorkDate  DATE;
DECLARE StartDate DATE;
DECLARE EndDate   DATE;

----------------------------------------------------------------
-- X is used set a breakpoint within ED Manager
----------------------------------------------------------------
DECLARE X INTEGER;

----------------------------------------------------------------
-- Get the current Year and Month
----------------------------------------------------------------
SET Today = Current_Date;
SET YYYY  = EXTRACT(YEAR FROM Today);
SET MM    = EXTRACT(Month FROM Today);

----------------------------------------------------------------
-- Set the WorkDate equal to the first day of the current month
-- by building a date string from the extracted date parts
-- Example: YYYY-MM-01
-- WHERE YYYY is the extracted Year
-- AND   MM   is the extracted Month
-- Make sure to pad any month less than 10 with a leading zero
----------------------------------------------------------------
SET DateStr = '';
SET DateStr = DateStr + CAST(YYYY as VARCHAR);
SET DateStr = DateStr + '-';
IF MM < 10 THEN
  SET DateStr = DateStr + '0';
END IF;
SET DateStr = DateStr + CAST(MM as VARCHAR);
SET DateStr = DateStr + '-01';
SET WorkDate  = CAST(DateStr as DATE);

----------------------------------------------------------------
-- For Previous month subtract one month from WorkDate
-- Set StartDate equal to the first day of the month and create
-- the EndDate by performing two simple date math operations
-- 1. Add one Month to the WorkDate
-- 2. Subtract one Day from the WorkDate
----------------------------------------------------------------
SET WorkDate  = WorkDate + Interval '-1' Month;
SET StartDate = WorkDate;
SET WorkDate  = WorkDate + Interval  '1' MONTH;
SET WorkDate  = WorkDate + Interval '-1' DAY;
SET EndDate   = WorkDate;

SET X = 1;
END

How to set the StartDate and EndDate for the Following Month


SCRIPT
BEGIN
----------------------------------------------------------------
-- This snippet of code sets the StartDate and EndDate to the 
-- first day  and last day of the following month
----------------------------------------------------------------
DECLARE Today     DATE;
DECLARE YYYY      INTEGER;
DECLARE MM        INTEGER;
DECLARE DateStr   VARCHAR(10);
DECLARE WorkDate  DATE;
DECLARE StartDate DATE;
DECLARE EndDate   DATE;

----------------------------------------------------------------
-- X is used set a breakpoint within ED Manager
----------------------------------------------------------------
DECLARE X INTEGER;

----------------------------------------------------------------
-- Get the current Year and Month
----------------------------------------------------------------
SET Today = Current_Date;
SET YYYY  = EXTRACT(YEAR FROM Today);
SET MM    = EXTRACT(Month FROM Today);

----------------------------------------------------------------
-- Set the WorkDate equal to the first day of the current month
-- by building a date string from the extracted date parts
-- Example: YYYY-MM-01
-- WHERE YYYY is the extracted Year
-- AND   MM   is the extracted Month
-- Make sure to pad any month less than 10 with a leading zero
----------------------------------------------------------------
SET DateStr = '';
SET DateStr = DateStr + CAST(YYYY as VARCHAR);
SET DateStr = DateStr + '-';
IF MM < 10 THEN
  SET DateStr = DateStr + '0';
END IF;
SET DateStr = DateStr + CAST(MM as VARCHAR);
SET DateStr = DateStr + '-01';
SET WorkDate  = CAST(DateStr as DATE);

----------------------------------------------------------------
-- For Following month add one month to WorkDate
-- Set StartDate equal to the first day of the month and create
-- the EndDate by performing two simple date math operations
-- 1. Add one Month to the WorkDate
-- 2. Subtract one Day from the WorkDate
----------------------------------------------------------------
SET WorkDate  = WorkDate + Interval '1' Month;
SET StartDate = WorkDate;
SET WorkDate  = WorkDate + Interval  '1' MONTH;
SET WorkDate  = WorkDate + Interval '-1' DAY;
SET EndDate   = WorkDate;

SET X = 1;
END



Enjoy,
Gunny Mike

Sunday, September 4, 2011

ElevateDB: Date Math 1

ElevateDB has just impressed me again the way it handles date math. I don't know if you have ever tried doing SQL Date Math but it can be tricky unless there is built in support.

Often times you need to add a Day or a Month or a Year to a given date. ElevateDB lets you do this and it works well.

I opened up a new SQL Window inside EDB Manager and tried executing the following:
SELECT
Current_Date as Today
I received an Error:

ElevateDB Error #700 An error was found in the statement at line 3 and column 1 (Missing FROM)

So I created a dummy table with one field and one record. Then I modified my original SQL as follows...
SELECT
Current_Date as Today,
FROM dummy
and it works great. Even though I'm not returning any real data from the "dummy" table.

Being inquisitive and wanting to see how well ElevateDB does "Date Math" I tried the following...
SELECT
Current_Date + INTERVAL '-4' DAY AS FourDaysAgo,
Current_Date + INTERVAL '-3' DAY AS ThreeDaysAgo,
Current_Date + INTERVAL '-2' DAY AS TwoDaysAgo,
Current_Date + INTERVAL '-1' DAY AS OneDayAgo,
Current_Date as Today,
Current_Date + INTERVAL '1' DAY AS OneDayFromNow,
Current_Date + INTERVAL '2' DAY AS TwoDaysFromNow,
Current_Date + INTERVAL '3' DAY AS ThreeDaysFromNow,
Current_Date + INTERVAL '4' DAY AS FourDaysFromNow
FROM dummy
and it works AWESOME. I tested going backwards until one day before March 1, 2011 testing leap year. I tested going forward until one day after Feb 28, 2012. I tested December 31st plus 1 Day and Jan 1st minus 1 Day. It's all good.

Now I know that using a dummy table this way probably isn't considered EDB best practices but it did allow me to get the information I was looking for. This method also works for selecting literal values.

I'm waiting to hear back from the ElevateDB boys on the proper way to return this kind of data but until then, I have a working model.

Semper Fi
Gunny Mike

Saturday, August 27, 2011

Making a ClientDataSet Talk to an MS Access Database 1

I purchased Cary Jensen's book called Delphi in Depth: ClientDataSets a couple weeks ago. It's a great book filled with lots of nuggets. You can only read so much before you need to practice by doing. All of Cary's examples use the DBDEMOS database that comes with Delphi.

So, I have decided to port these examples over so they talk to a MS Access database. I figure this is a great way to learn. For me this is a pain-stakingly slow process, because I want to learn (I mean really learn) how to do this well.

I have just gotten to page 53 of Chapter 3 and decided to blog about what I've done so far.

I substituted the BDE.TTable for a dbGo.TADOTable. I also had to use a dbGo.TADOConnection. The TADOConnection comes with a built in Connection String Builder which works very well.

Anyway, here's where the chicken and the egg thing come into play. In order for this to work you need an MS Access database. So, I created a very simple database using different table names from the DBDEMOS so I can learn how to wire everything up properly.

I set set the TADOConnection.Connected property to true so I can see stuff happening in the IDE. I decided to add a couple more tables to my MS Access database. With my project loaded in the IDE I attempted to open my MS Access database by doubl-clicking on the mdb file... Well, my computer hung. I had to do a hard reboot. Keep this in mind if you go back and forth between Delphi and MS Access.


Another thing that was weird. I tried applying the updates ClientDataSet1.ApplyUpdates(-1); and I got the following error:









So, again Jensen to the rescue. On page 52 he talks about using the ResolveToDataSet property of the DataSetProvider component. I set this property to True and now my updates from with my Delphi application are showing up in the MS Access database.

I'm off to learn some more. I'll share anything that's good to know along the way.

Semper Fi
Gunny Mike