Category: Visual Foxpro

Word Merges

For years and years now, I’ve been merging Foxpro data in Microsoft Word. It doesn’t always work smoothly and I’ve spent probably more time than I should walking clients through ODBC driver installs, but its always work and, hey, if it ain’t broke – don’t fix it.

Word 2016 broke it. Stupid Word 2016.

Merging Foxpro to Word 2016 gets an “Could not find installable ISAM” error. Crap. I decided it was probably time I stopped trying to merge with Foxpro data (OK, first I tried to Google a solution but couldn’t find one, THEN I decided not to use Fox data anymore).

I decided I’d just convert the Fox data to Excel in my program and then merge that. Works great, except that Word 2016 pops up a “Select Table” dialogue box and asks you to select a worksheet. Stupid Work 2016. DisplayAlerts = .f. does not stop that behavior. Stupid, stupid Work 2016.

A bit of googling turned up that I should pass a select statement to bypass the dialogue box. It looks like this then:

this.o.ActiveDocument.MailMerge.OpenDataSource(lFile,,,,,,,,,,,,”SELECT * FROM ‘Sheet1$'”)

Still not working. Stupid Word 2016. Study the google result a little more carefully, tweak the statement to this:

this.o.ActiveDocument.MailMerge.OpenDataSource(lFile,,,,,,,,,,,,”SELECT * FROM `Sheet1$`”)

Voila! Works. You can totally see the difference right? The Sheet1$ has to have a backwards quote mark around it, not a regular quote mark. WTH is a backwards quote mark? Stupid Word 2016. But it works.

Advertisements

Alter Table Mystery Fail

So I’ve got a bit of code in one of my products that does about 30 Alter Table Add Column commands in a row. Has worked fine for 15+ years, but today it starts failing for one of my clients.

The failure is inconsistent – some fields won’t get added some times, other times other fields aren’t added. It was usually 2-4 fields out of the 30 that wouldn’t add. Even more bizarrely, there’s no error message. The command acts like it works, carries on merrily, but the field is not added to the table.

I know about the problem with Alter Table and Cursors, but this is a table. Tried a FLUSH. Tried a NOVALIDATE. Those didn’t help.

In the end, I simply had to add some code to double-check if the field was actually in the table (the Field() worked reliably). If the field did not exist, I paused for a second and then retried the Alter Table command. I maxed out the retry at 10 times, but I never saw it take more than 1 try to work.

This was a brand new laptop running Windows 10. No idea what the underlying cause is, but I’m thankful I do all my Alter Table commands through a generic utility rather than having to search through all my code, for all my clients, and fix all of them.

Stripe Plan and Subscription Functions

I’ve updated StripeX with new Plan & Subscription functions.

Stripes terminology is slightly confusing:

  • A “Plan” is a subscription you sell. So “Tech Support $50/month” or “$3 per month per user license” is a Plan. Your stripe account can have multiple plans.
  • A “Subscription” is when a customer subscribes to a specific plan. A customer can subscribe to more than one plan.
  • So customers have subscriptions while your account has plans.

The .PlanList() function will build a cursor of all the plans on your account while the .PlanRetrieve(id) function will get the information for a specific plan:

There are four functions that work with subscriptions (a customer must have a Card on file to add subscriptions. Card functions are explained here):

  • SubscriptionCreate – Creates a subscription for a customer
  • SubscriptionDelete – Remove a subscription from a customer
  • SubscriptionList – Builds a cursor of all the subscriptions a customer has
  • SubscriptionRetrieve – Gets information for one subscription

 

 

 

Stripe Card Functions

Update 3/20/17: For new accounts, Stripe is requiring TLS 1.2. The CURL library I’m using to talk with Stripe appears to support only TLS 1.1. Until this is figured out, StripeX will NOT work with new Stripe accounts. It continues to work with OLD Stripe accounts. Sorry for any trouble. Hopefully I can track down a solution.

———-

I’ve released a new version of StripeX on VFPX.¬†This version adds several Card functions that allow you to save a credit card to a customer. This is handy for setting up subscription (which I’ll be adding next to StripeX) or if you need to routinely charge a card for a customer. The new methods are:

CardCreate() – Adds a credit card to a customer
CardDelete() – Deletes a credit card from a customer
CardLIst() – Builds a cursor of all the credit cards on the customer
CardRetrieve() – Retrieves information for a particular card

ObjectExtract() – Is a new utility method that retrieves a value from Stripe objects. You can use that, for example, to retrieve the information from the CardRetrieve() method

Here’s some sample code using those functions. It creates a new card for a customer, gets a list of existing cards, retrieves the first card found, prints some info for that card, and then deletes the card that was added card.

 

DebugX

For a while, I’ve had a simple little debug class that let’s me output messages to the debug window or to a text file. For example in my application that sends an email, if the sending fails for some reason, I create a little text file the user can send me:

if !oMail.Send()

local oDebug

oDebug = newobject(“DebugX”)

oDebug.Message(“Email Failed”)

oDebug.Message(“Email address was: ” + oMail.cSendTo)

oDebug.Message(“Error message was: ” + oMail.cErrorMsg)

endif

This class has a couple little interesting features:

  • As noted, the message function can send to the debug window or to a text file. Just set the .cOutputType property.
  • Every .Message() gets a date + time stamp so I know when it happens.
  • I know this never happens to you, but I sometimes forget to remove the debug code before sending to production. This class has a lIsDevelopement property. If it’s not developement, then the .Message() doesn’t do anything.

Tamar‘s talk about speeding up Foxpro code at Southwest Fox prompted me to add a couple new functions:

  • Added a .Start() and .Stop() to start/stop a timer. Any .Message() that is sent while the timer is going will include the elapsed seconds. This works correctly over Midnight as well.
  • Added a .Loop() function that will loop a .nLoop number of times. This is handy if one pass through your code is not enough to accurately time how long it takes. If you accidentally leave this code in for production, nLoop always resets to 1.

So you can do things like:

local oDebug

oDebug = newobject(“DebugX”)

oDebug.Message(“Debug Starting”)

oDebug.Start(“Start timing some code, Loop 4 times”)

oDebug.nLoop = 4

do while oDebug.Loop()

oDebug.Message(“Pass # ” + tran(oDebug.nLoop))

<some Foxpro code I want to time >

enddo

oDebug.Stop(“End of debugging test”)

Here’s the code:

TwilioX

I’ve released TwilioX to VFPX.

Twilio is a service for sending text messages through their API. It’s costs are very reasonable – $1 a month and then .75 cents for each text. Twilio handles all the technical part of sending a text making things very easy.

The code for sending text is also pretty darn easy:

SET PROCEDURE TO w:\vfp7com\prog\TwilioX
PUBLIC o 
o = NEWOBJECT("TwilioX")
o.cAccount = "YourAccount" 
o.cAuthToken = "YourAuthToken" 
o.cFrom = "YourTwilioNumber" 

IF !o.SendText("ToNumber", "Messsage")
    ?"Send", "Failed", o.cErrorMessage
    return
ELSE
    * Good Send
endif