Sunday, March 9, 2014

Get More out of StackOverflow

It's no secret that StackOverflow or SO as it's commonly referred to is one of the best resources for Delphi enthusiasts. We all have some favorite questions, favorite answers and favorite users out there.

What makes StackOverflow so useful are tags. Tags are the single most important feature. Here is a snippet of what you see when you search tags for Delphi:

StackOverflow Tag Search - Delphi


If you mouseover a tag there is a little pop-up that gives a description of the tag along with some very interesting links. One of the most interesting links is the "top users" link. This "top users" link is how you can get more out of StackOverflow.

By following this link you get a list of which users have answered the most questions and which users have asked the most questions relating to this tag. By drilling down onto the users profile, you can see all the answers and questions this user has participated in.

You can very quickly build a list of your favorite StackOverflow Delphi users. Reading answers by these users will most definitely increase your knowledge about Delphi.

Delphi Tags Top Users
http://stackoverflow.com/tags/delphi/topusers
http://stackoverflow.com/tags/delphi-xe5/topusers
http://stackoverflow.com/tags/delphi-xe4/topusers
http://stackoverflow.com/tags/delphi-xe3/topusers
http://stackoverflow.com/tags/delphi-xe2/topusers
http://stackoverflow.com/tags/delphi-xe/topusers
http://stackoverflow.com/tags/delphi-2010/topusers
http://stackoverflow.com/tags/delphi-7/topusers

FireMonkey Tags Top Users
http://stackoverflow.com/tags/firemonkey/topusers
http://stackoverflow.com/tags/firemonkey-fm3/topusers
http://stackoverflow.com/tags/firemonkey-fm2/topusers

Semper Fi,
Gunny Mike




Saturday, March 8, 2014

Delphi Product and Compiler Versions Quick Reference

I was doing some research on Delphi ClientDataSet QC issues at http://qc.embarcadero.com/ and noticed that the Delphi Product Versions are reported as 18.0, 16.4, etc. When an issue is resolved they show the Resolved in Build as XE5 or sometimes they show it as a number such as 17.0.

When I think of Delphi versions I think of XE5, XE4, D7. I don't think of 19, or 18, or 7. Here is an Embarcadero quick reference webpage that lists all the different Product versions for Delphi.

http://docwiki.embarcadero.com/RADStudio/XE5/en/Compiler_Versions


Semper Fi,
Gunny Mike

Tuesday, January 14, 2014

Embarcadero's Upgrade Policy is Deceiving

I am so frustrated and angry with Embarcadero right now. You have no idea how angry I am. Embarcadero's upgrade pricing policy is deceiving.


I upgraded to XE4 Enterprise from D2010 Professional in May of 2013. I blogged about my decision on May 19, 2013. (You can read about it here)


My upgrade decision was mostly made based on Embarcadero stating that the upgrade to XE4 is only valid for users of D2010 and higher. I did not want to miss out on an opportunity. It only stood to reason that when XE5 came out Embarcadero would only allow upgrade pricing from XE and higher.


Like all of you, I received all the year end marketing emails from Embarcadero. Needless to say, I did not take advantage of these year end offers.


I continued to receive upgrade notifications from Embarcadero. So, I decided to follow the embedded links within the email and now I discover that Embarcadero is allowing upgrades to XE5 to users of D2009 and higher.


THIS IS AN OUTRAGE


If I had waited a few short months I could have spent my upgrade money and received XE5. Now, I have XE4 Enterprise and it's going to cost me another 1,500 dollars to upgrade to XE5. This has got me so angry I don't know what to do. (I'm one pissed off Marine)


I'm a die-hard Delphi fanatic like most of you are. I have a love/hate relationship with Delphi mainly because it takes so dang long to learn how to do something in Delphi and after you figure out how to do it you say to yourself... "It shouldn't have taken that long."


I'm starting to really resent Embarcadero for what I consider to be deceptive marketing and upgrade policies.


I am not a happy camper right now.


Gunny Mike

Sunday, November 10, 2013

Everyone Needs A Miyagi

Today is the Marine Corps' 238th birthday. Although I've been out of the Marine Corps since 1999 there's a saying that all Marines live by... "You can take the man out of the Marine Corps but you can't take the Marine Corps out of the man."

I just received a traditional "Happy Birthday" text response on my phone from Mitch Perry, one of my best friends of my Marine Corps days. I love this guy. Here's what he said...
"Same to you bud! I am sitting here drinking coffee in my dress blue coat, I might be losing it... HELP? Oh oh oh life goes on !"
 So this got me thinking back to my earlier days in the Marine Corps. When you spend 20 years in the Marines you meet a lot of people. When I was a young Marine on my first four year enlistment I met a Marine named Staff Sergeant Reggie Wournos. Reggie was my Miyagi.

Reggie was one of the most squared away Marines I ever met. He taught me the Marine Corps version of "Wax on... Wax off", "Paint the fence" and "Sand the floor".

I'm not the only one that Reggie helped along the way. He took several of us young Marines under his wing and nurtured us along. If you ask the entire group of enlisted Marines from Headquarters and Maintenance Squadron 16, GSE - MCAS Tustin you will find you get the same type of response.  Here's a picture. Reggie is front row left in the bottom photograph.

This would be an awesome story if it ended right here, but it doesn't. For those of you that don't know how military life works, everybody moves on to new locations after 2-3 years. So, you get to hang with the same group of guys for a year or two and then you, or they, or both move on.

A few years later I'm working at MCAS Cherry Point, North Carolina. I had been promoted a couple times and now I was a sergeant. I have a new boss named Gunnery Sergeant Bill Wallace. You guessed it he's Miyagi #2. Wallace taught me a different set of skills. Wallace had the reputation both inside and outside of our organization as the "guy who's got his shit together".

So, you could say I was a lucky guy to have two Miyagi's. But if you can believe it, this gets even better.

In 2008 a bunch of us from GSE (the 1980 group) decide to get together in Memphis for a weekend. Most of us haven't seen each other in 25+ years. It was a pretty awesome time. So, I made public toast to Reggie thanking him for his early mentoring and telling him that he was my Miyagi. Everyone felt the same... Reggie is just one of those guys.

I was having a private conversation with Reggie. We were both retired, me as a Gunnery Sergeant and Reggie as Chief Warrant Officer 4. I thanked him for being my Miyagi which he humble tried to deny. Then I asked him who his Miyagi was?

He looked at me and said "Bill Wallace".

Happy Birthday Marines
Semper Fi
Gunny Mike

 

Friday, August 23, 2013

The One Manual Every Delphi Programmer Should Have!


I have always stayed away from using Delphi's DBGrid because it gave me the feeling of being in the cockpit of an airplane without a clue, as to what all the controls are, or even where to look first. I've decided to roll up my sleeves and get over my fear and anxiety of Delphi's DBGrid.

I'm currently using XE4 and I've been struggling with data validation within a DBGrid as you can see from a recent SO post How to get the value that caused the TDBGridInplaceEdit error?

After reading the answer I got from @bummi, I started googling related topics. Then I remembered I have a copy of Borland's Delphi 7 Developer's Guide.


Delphi 7 Developer's Guide

I quickly turned to Chapter 25 and found all the information I need to know, written in a friendly and very informative way. It's perfect. Each topic builds upon the previous topic giving a full treatment of the subject matter. Here is the table of contents for Chapter 25 of Borland's Delphi 7 Developer Guide:

Chapter 25Page
Working with field components 25-1
Dynamic field components 25-2
Persistent field components 25-3
    Creating persistent fields 25-4
    Arranging persistent fields 25-5
    Defining new persistent fields 25-5
        Defining a data field 25-6
        Defining a calculated field 25-7
        Programming a calculated field 25-8
        Defining a lookup field 25-9
        Defining an aggregate field 25-10
    Deleting persistent field components 25-11
    Setting persistent field properties and events 25-11
        Setting display and edit properties at design time 25-11
        Setting field component properties at runtime 25-13
        Creating attribute sets for field components 25-13
        Associating attribute sets with field components 25-14
        Removing attribute associations 25-14
        Controlling and masking user input 25-15
        Using default formatting for numeric, date, and time fields 25-15
        Handling events 25-16
Working with field component methods at runtime 25-17
Displaying, converting, and accessing field values 25-18
    Displaying field component values in standard controls 25-18
    Converting field values 25-19
    Accessing field values with the default dataset property 25-20
    Accessing field values with a dataset’s Fields property 25-21
    Accessing field values with a dataset’s FieldByName method 25-21
Setting a default value for a field 25-22
Working with constraints 25-22
    Creating a custom constraint 25-22
    Using server constraints 25-23
Using object fields 25-23
    Displaying ADT and array fields 25-24
    Working with ADT fields 25-25
        Using persistent field components 25-25
        Using the dataset’s FieldByName method 25-25
        Using the dateset’s FieldValues property 25-25
        Using the ADT field’s FieldValues property 25-26
        Using the ADT field’s Fields property 25-26
    Working with array fields 25-26
        Using persistent fields 25-26
        Using the array field’s FieldValues property 25-27
        Using the array field’s Fields property 25-27
    Working with dataset fields 25-27
        Displaying dataset fields 25-27
        Accessing data in a nested dataset 25-28
    Working with reference fields 25-28
        Displaying reference fields 25-28
        Accessing data in a reference field 25-29

I've already printed out Chapter 25 and plan to study it this weekend. The manual is 1,106 pages long. I plan on printing the chapters I need as I go. And yes I did buy paper that's already punched with 3-holes.

I don't care what version of Delphi you are using this manual is relevant and will make your life easier. Download your copy of Borland's Delphi 7 Developer Guide now!

If we could only get EMBT to create an updated version of this Delphi classic!

Semper Fi,
Gunny Mike

Sunday, August 11, 2013

Format Numbers with an ElevateDB Function

There are times when I want numeric data coming out of a database formatted with a thousands separator and set number of decimal places. I'd rather see large numbers formatted as 123,740.00 rather than 123740. To me formatted numbers are just easier to read. Unfortunately, ElevateDB does not have a built in function similar to Microsoft's CONVERT.

However, you can create your own CONVERT function within ElevateDB quite easily. ElevateDB has two statements that make the job of formating numbers fairly easy. The first is the LABEL statement and the second is the LEAVE statement. The LABEL statement lets you set up a block of code. For example:
MyFistLabel:
BEGIN
  Do Something1;
  Do Something2;
  Do Something3;
  Do Something4;
  Do Something5;
END; --MyFistLabel
The LEAVE statement lets you exit a block of code. For Example:
MyFistLabel:
BEGIN
  Do Something1;
  Do Something2;
  Do Something3;
  IF Something3 = Done THEN
    LEAVE MyFistLabel
  END IF;
  Do Something4;
  Do Something5;
END; --MyFistLabel
So let's set out to create a function that formats numbers. This function will have two input parameters Value and Decimals. Value is the number to be formatted and Decimals is the number of decimal places. I built this function using two labels. One label that handles zero decimal places and one label that handles non zero decimal places. Here is the stubbed out concept:
----------------------------------------------------------------
ProcessZeroDecimals:
----------------------------------------------------------------
BEGIN
  -- Exit if Decimals parameter is other than 0 (zero)
  IF DECIMALS <> 0 THEN LEAVE ProcessZeroDecimals; END IF;
  -- Perform if Decimals parameter is equal to 0 (zero)
  Code Goes Here
  Code Goes Here
  Code Goes Here
----------------------------------------------------------------
END;--ProcessZeroDecimals:
----------------------------------------------------------------

----------------------------------------------------------------
ProcessNonZeroDecimals:
----------------------------------------------------------------
BEGIN
  -- Exit if Decimals parameter is equal to 0 (zero)
  IF DECIMALS = 0 THEN LEAVE ProcessNonZeroDecimals; END IF;
  -- Perform if Decimals parameter is other than 0 (zero)
  Code Goes Here
  Code Goes Here
  Code Goes Here
----------------------------------------------------------------
END; --ProcessNonZeroDecimals:
----------------------------------------------------------------
By testing the value of Decimals first we will either decide to LEAVE the code block or perform the code within that code block. The use of LABEL combined with the LEAVE statement makes for a very elegant solution. Here is the complete ElevateDB funtion:
CREATE FUNCTION "fFormatThousands"
(
 INOUT "Value" DECIMAL(19,4)
,INOUT "Decimals" INTEGER
)
RETURNS VARCHAR(20) COLLATE UNI_WI
BEGIN

DECLARE Separator VARCHAR(1);
DECLARE Str1      VARCHAR(30);
DECLARE Str2      VARCHAR(30);

DECLARE StrLength  INTEGER;
DECLARE ZeroPad    INTEGER;
DECLARE DecimalPos INTEGER;

DECLARE i INTEGER;
DECLARE j INTEGER;

SET Separator = ',';
SET Str1      = '';
SET Str2      = '';
SET ZeroPad   = 0;

CASE DECIMALS
  WHEN 0 THEN SET Value = ROUND(Value to 0);
  WHEN 1 THEN SET Value = ROUND(Value to 1);
  WHEN 2 THEN SET Value = ROUND(Value to 2);
  WHEN 3 THEN SET Value = ROUND(Value to 3);
  WHEN 4 THEN SET Value = ROUND(Value to 4);
  ELSE
    BEGIN
      SET Value = ROUND(Value to 2);
      SET Decimals = 2;
    END;
END CASE;
SET Str1 = CAST(Value as VARCHAR);

----------------------------------------------------------------
ProcessZeroDecimals:
----------------------------------------------------------------
BEGIN
  -- Exit if Decimals parameter is other than 0 (zero)
  IF DECIMALS <> 0 THEN LEAVE ProcessZeroDecimals; END IF;
  -- Perform if Decimals parameter is equal to 0 (zero)
  SET StrLength = LENGTH(Str1);
  SET Str2 = '';
  SET i = 0;
  SET j = StrLength;
  WHILE j > 0 DO
    SET Str2 = SUBSTRING(Str1, j for 1) + Str2;
    SET i = i + 1;
    SET j = j - 1;
    IF (i MOD 3 = 0) AND (j > 0) THEN
      SET Str2 = Separator + Str2;
    END IF;
  END WHILE;
----------------------------------------------------------------
END;--ProcessZeroDecimals:
----------------------------------------------------------------

----------------------------------------------------------------
ProcessNonZeroDecimals:
----------------------------------------------------------------
BEGIN
  -- Exit if Decimals parameter is equal to 0 (zero)
  IF DECIMALS = 0 THEN LEAVE ProcessNonZeroDecimals; END IF;
  -- Perform if Decimals parameter is other than 0 (zero)
  SET DecimalPos = POSITION('.' IN Str1);
  IF DecimalPos = 0 then
    CASE Decimals
      WHEN 1 THEN SET Str1 = Str1 + '.0';
      WHEN 2 THEN SET Str1 = Str1 + '.00';
      WHEN 3 THEN SET Str1 = Str1 + '.000';
      WHEN 4 THEN SET Str1 = Str1 + '.00000';
    END Case;
  END IF;
  SET StrLength = LENGTH(Str1);
  SET DecimalPos = POSITION('.' IN Str1);
  SET ZeroPad = Decimals - (StrLength - DecimalPos);
  SET Str2 = SUBSTRING(Str1, DecimalPos for Decimals+1);
  SET i = 0;
  SET j = DecimalPos -1;
  WHILE j > 0 DO
    SET Str2 = SUBSTRING(Str1, j for 1) + Str2;
    SET i = i + 1;
    SET j = j - 1;
    IF (i MOD 3 = 0) AND (j > 0) THEN
      SET Str2 = Separator + Str2;
    END IF;
  END WHILE;
  CASE ZeroPad
    WHEN 1 THEN SET Str2 = Str2 + '0';
    WHEN 2 THEN SET Str2 = Str2 + '00';
    WHEN 3 THEN SET Str2 = Str2 + '000';
    WHEN 4 THEN SET Str2 = Str2 + '0000';
  END CASE;
----------------------------------------------------------------
END; --ProcessNonZeroDecimals:
----------------------------------------------------------------

RETURN str2; 

END
VERSION 1.00!
Here is the fFormatThousands function at work against the DBDemos database.
SELECT
 OrderNo
,CustNo
,fFormatThousands(ItemsTotal,2) as "Items Total"
,fFormatThousands(AmountPaid,2) as "Amount Paid"
,fFormatThousands(ItemsTotal - AmountPaid,2) as "Balance Due"
FROM orders
ORDER BY
ItemsTotal - AmountPaid DESC;

 
Semper Fi,
Gunny Mike

Tuesday, July 23, 2013

David I to Discuss Mobile & Mac at the 2013 ISVCon

The 2013 Independent Software Vendor Conference (ISVCon), scheduled for September 27-29, 2013 at the Atlantis Casino Resort in Reno, Nevada, has released information about the panel discussions and seminars that will be presented. Designed to deliver the latest marketing ideas to small software development firms, this year’s conference includes:
  • “Sell Software on Facebook” by Nico Westerdale of BitsDuJour – Can independent software vendors (ISVs) make money selling software on Facebook? Yes. More than half of the people in the US have Facebook accounts. Learn practical ways to build your fanbase, and create posts that generate traffic.
  • “Conversations to Create More Customers” by Jessica Dewell of Red Direction – Move more software customers through your company’s sales cycle by changing from reactive conversations (such as answering email inquiries) to proactive conversations (such as listening and starting conversations.)
  • “Growing your ISV business to Multi-Device with Mobile and Mac” by David Interstimone (David I) of Embarcadero – Discover how to increase software sales by supporting a mix of client devices, UI approaches, OS versions, and emerging form factors.
  • “Connected Apps: The New Normal” by Leyla Seka of Salesforce.com – Learn to build and deploy connected apps as your software development business evolves from the desktop/laptop world to the cloud and mobile environments.
  • “33 High Tech Business Myths, and How They Can Hurt Your Company” by Gary Elfring of Elfring Fonts Inc. – Gain insights into distinguishing between valid business ideas and the myths, folklore, and misinformation that can hurt your company.
  • “Google AdWords – Winning the War and Making It Work” by Aaron Weiner of Software Promotions – Learn how recent AdWords changes will impact your account’s performance, and how you can overcome any problems.
Other seminar titles include:
  • Practical Roadmap to High Performing Websites
  • Secondary Offer Networks
  • The Cloud for ISVs
  • Avoiding Problems When Hiring and Working with Freelancers
Visit http://www.isvcon.org/speakers.php to read about new seminars that will be added during the summer.

Sign up for the conference by September 22 to take advantage of ISVCon’s $820.50(US) registration fee. Registration includes three days of intense education and networking opportunities plus a Thursday evening reception, and break rooms full of snacks and helpful representatives from the conference’s sponsors.

Previously known as the Software Industry Conference (SIC), ISVCon carries on a 22 year tradition of supporting independent software developers’ business and marketing efforts with seminars, presentations, and networking opportunities.

ISVCon is owned and presented by The Association of Software Professionals. Sponsors for ISVCon 2013 include FastSpring, Avangate, Tightrope Interactive, Software Promotions, Greentram Software, and The Association of Software Professionals. Visit http://www.isvcon.org/ for more information about attending ISVCon 2013. Or visit http://www.isvcon.org/sponsors.php for information about sponsoring the conference.