No time for Textworks date fields

by Peter Tyrrell Friday, June 01, 2007 12:33 PM

Ha ha! That was a pun, that was. "No time for Textworks date fields." Phew... that is the kind of half-inflated rubber-mattress-smelling type of humour I am capable of, here on this highly informative forum.

So I discovered the other day, quite by accident, that Inmagic textbase Date fields are exactly that and no more. By which I mean: Date fields are not DateTime fields.

Perhaps on the surface this seems a trivial distinction. Let me assure you, my dear confidant, it is not.

You can enter time information in a non-strict Date field, or one that has trailing text enabled, but the time you enter is just a string. It is not understood as a chronological statement. You might as well type "blah blah blah" instead of "09:00:00 AM" for all the good it does you, because you can't search for, or sort by, time. You and I know that 1:00:00 PM comes after 12:00:00 PM, but Inmagic doesn't.

Here's an example where I told the report to sort by a date field. Note that it is NOT sorting chronologically, but rather, numerically.


I'm so surprised that there is no way to handle chronological data. In the languages, programming environments, and database systems I work with, it's just assumed that Date fields, classes, and variables are date-plus-time: DateTime objects. The assumption is such that you can call a DateTime object a Date, in fact, and everyone already knows you really mean DateTime but aren't pretentious enough to have to say it. (The javascript Date object is an example off the top of my head.)

A DateTime object can of course show a date without time, but that's just a matter of formatting. The information about time is still in there. And, even if you instantiate a DateTime object with a date string and don't include the time, the time defaults to 00:00:00.

Anyway, I'm not sure what to do about this.

Watch out for file encoding when importing into Inmagic Textworks

by Peter Tyrrell Thursday, May 31, 2007 2:21 PM

When importing a text file into a Textworks database, make sure it is ANSI/ASCII encoded, not UTF-8 or otherwise.

You can't tell just by looking at the text how the file has been encoded, but a good text editor will tell you, and allow you to save as another encoding format.

Note that Textworks is not going to warn you about encoding incompatibilities specifically. It's just going to drastically misinterpret characters. Lucky for me this happened before import got underway, as the misinterpretation involved a field name match.

As a nota bene, the above shows how misleading it is to refer to any delimited text file as an "ASCII delimited file," as I've heard them referred to before. Unless of course you happen to mean literally ASCII-encoded as opposed to UTF.

How to serialize an object to Inmagic Textworks userStore with JSON

by Peter Tyrrell Thursday, May 17, 2007 11:28 PM

The Inmagic DB/Textworks and CS/Textworks script object model includes a Store object which you can use to store strings. It's a simple dictionary object of key/value pairs where the key is a unique identifier for the corresponding value. There are two versions of the Store object: userStore and sessionStore. The first persists key/value pairs to the local machine, while sessionStore only sticks around so long as Textworks is open.

It's a lot like writing cookies. If you need to keep some values around to reuse that would otherwise disappear when the form unloads, you need to use the Store object.


var myString = "foo";

Application.userStore.value("keyName") = myString;



var myString = "";

myString = Application.userStore.value("keyName");

Unfortunately it only stores a string, like a cookie. If you like to work with objects, it doesn't seem right to store individual object properties as separate key/value pairs. Especially if you decide to change the object profile down the road, because you will have to rewrite code. It would be great to simply store an object's state and pick it back up again whenever.

Serialize the object

Serialization is the act of saving an object into a binary or text format. Aha! Text format - that's a string. We can save our object to a string, and persist it to the Store object. Then later we can get that string and deserialize back into an object.

What's the best way to store the string so we can easily turn it back into an object? We could roll our own format, but it's best to stick with something already known and tested and out there. So let's use JSON. JSON stands for JavaScript Object Notation and it's a text-based human-readable format for representing data structures, commonly for transmission over an HTTP connection. Basically it's AJAX without the X (Object Notation instead of XML).

JSON Example

In the following example, we define a Person object, instantiate it, set its properties, serialize it, store it, retrieve it, and deserialize back into an object.

function Person()






// instantiate a Person

var person = new Person();

person.Name = "Joe Blow";

person.BirthDate = new Date("July 1, 1975 08:30:00");


// serialize the Person object

var strPerson = person.toJSONString();


strPerson =

{"name":"Joe Blow","BirthDate":"1975-07-01T08:30:00"}



// store the serialized Person

Application.userStore.value("mykey") = strPerson;


// retrieve the serialized Person

var s = Application.userStore.value("mykey");


// deserialize from string back into object

var o = s.parseJSON();

Pretty simple!

JSON Source Code

The prototype functions toJSONString() and parseJSON() are provided by an open source JSON parser and stringifier at which can be compressed to less than 2000 characters and placed in the form script.

toJSONString() serializes strings, dates, arrays, booleans, numbers, nested versions of these... pretty much anything. parseJSON() is a more secure rewrite of javascript eval which limits itself to valid JSON notation only.

A Short Aside About Eval

If you're not already aware of how powerful eval is, consider that you can pass in a string and have it interpreted as code. You can say:

eval("var a = 1");

and thereafter have a variable, a, which equals 1. This is incredibly handy, but also a security concern, so you would never eval anything you didn't have complete trust in. You can directly eval a JSON string and magically get your object back, but parseJSON() is safer.

Handling Inmagic Textworks javascript errors

by Peter Tyrrell Tuesday, May 15, 2007 2:40 PM

The scripting environment within Inmagic DB/Textworks (or CS/Textworks) is extremely primitive. Controls you want to interact with have to be declared in an environment separate from the form designer and it's hard to write code longer than 100 lines because there's no tab character or ctrl-a select all, let alone syntax highlighting or intellisense. It's very easy to lose your way if your script does anything beyond "hello world."

The most difficult thing to deal with is that any javascript error encountered does not actually throw an error. Things just progress... until they don't. No error thrown, no feedback, no nothing. It makes debugging a nightmare. What I have done until recently is insert a million-and-one trace statements that write to a trace box over on the side of the form, which at least tells me how far progress went and gives me a clue as to the general area things went wrong.

But I've recently realized I *can* throw (and handle) an error, if I wrap logical blocks of code in try/catch/finally statements. Can't believe it took me so long to cotton on to this. Now I can get detailed info about unanticipated exceptions as well as the anticipated ones. It makes my life better until I can boot up Visual Studio and bask once again in its warm developer-friendly glow.

Play "spot da error":

Yeah, "rs" is an undeclared variable. That's what happens when you refactor manually. Without try/catch this little problem becomes extremely elusive.

UPDATE: The picture has syntax highlighting because I do all scripting in UltraEdit. (Also features code folding, a jump-to-function list, etc.)

Textbase help won't launch on Vista

by Peter Tyrrell Friday, April 13, 2007 9:43 AM

Whether you are using Inmagic CS/TextWorks (v.9 or less) or Inmagic DB/TextWorks (v.10 or less) on Vista, you will see something like the following error message when you try to use Help.

Why is that? Well, it's a long story* but the gist of it is, the help file was created in a format that is not, by default, supported by Windows Vista.

Fortunately, you *can* go and download the software which will let Vista use these older-style help files. (Anything that has the *.hlp filename extension.)

Get WinHlp32.exe for Windows Vista:

* Okay, fine, here's the long story (taken verbatim from Microsoft site): "Windows Help (WinHlp32.exe) is a Help program that has been included with Microsoft Windows versions starting with the Microsoft Windows 3.1 operating system. However, the Windows Help program has not had a major update for many releases and no longer meets Microsoft's standards. Therefore, starting with the release of Windows Vista, the Windows Help program will not ship as a feature of Windows."

How Microsoft can get away with the cussed irony of condemning their own software for not meeting their standards is beyond me.

Month List