Jump to content

Problems with multiple external data files?


rbosworth

Recommended Posts

I have FusionPro setup to pull data successfuly from one other external data file.... but when I try to reference a second one, I can't make it work. None of the functions related to that file seem to work such as .recordCount or .findRecord.

 

I've tried both a csv file and a tab delimited file.... but I suspect the problem may be with the data file itself and I can't figure out why. Is there any known issues that would cause a datafile to have problems or steps I can take to start troubleshooting? Here is my script:

 

//BIKES
returnStr = '<table columns=2 title=above headershading=black,10 shadestyle=by:row;first:1,black,0;next:1,black,10><column width=35400><column width=14400><title gap=60><b>Bikes</b></title><row type=header><cell margins=top:0;bottom:60><b>Model<cell margins=top:0;bottom:60>Mileage</b>';

if(FusionPro.Composition.isPreview == true || FusionPro.inValidation == true)
{
   Rule("OnJobStart");
}
var matchBID = Field("id");

var recordWalker = bikesDF.FindRecord("member_id", matchBID);
for (; recordWalker <= bikesDF.recordCount; recordWalker++)
{
   var bikesCustomerID = bikesDF.GetFieldValue(recordWalker,"member_id");
   if (matchBID != bikesCustomerID) break;
   var tempBikeYear= bikesDF.GetFieldValue(recordWalker, "year");    
   var tempBikeModel = bikesDF.GetFieldValue(recordWalker, "model");
   var tempBikeMileage = bikesDF.GetFieldValue(recordWalker, "miles");
   returnStr += '<row><cell margins=top:0;bottom:60> ' + tempBikeYear + ' ' + tempBikeModel + '<cell margins=top:0;bottom:60>' + tempBikeMileage;
}
returnStr += '</table><br>TEST::: ' + matchBID + ' ' + recordWalker + ' ' + bikesDF.FindRecord("member_id", matchBID);
return returnStr; 

 

Here's a sample dataset:

 

model miles member_id year id archive
Test Bike 1 1010 550022 99 4 0
Dyna Low Rider FXDL 143 550022 2001 14 0
FAT BOY 1500 550026 99 5 0
Test Bike 1 500 550026 88 6 0
Buell Firebolt XB9R 15 550030 2001 13 0
SCHWINN 375 550034 98 7 0
Sportster 883c Custom 883 20000 550046 1995 12 0
Yamaha 45000 550046 1955 22 0
Sportster 837 XLH 0 550048 1995 9 0
Softail Deuce FXSTD/FXSTDI 20000 550048 1995 10 0
Softail Deuce FXSTD/FXSTDI 20000 550048 1995 11 0
Sportster 1200 Custom XL1200C 1000 550051 1999 262 0
Heritage Softail Classic FLSTC/FLSTCI 36400 550051 1998 263 0
Super Glide 2 FXR2 25000 550051 1999 264 0
Sportster 883 Custom XL883C 2000 550051 2000 265 0
FL 1200 0 550051 1976 5787 0
Street Glide FLHX 2000 550055 2006 13770 0
Road Glide FLTRI 4000 550065 2001 2661 0
Custom 1200 550065 2004 6077 0 

 

When I run a very, very similar script on another datafile it comes back fine. Just for fun... here's my onJobRun:

 

 
bikesDF = new ExternalDataFileEx('c:\bikes.txt', '\t');
purchasesDF = new ExternalDataFileEx('c:\purchases.txt', '\t');

if(purchasesDF.valid != true)
{
   Print('Failed to link to the external data file in OnJobStart');
}
if(bikesDF.valid != true)
{
   Print('Failed to link to the external data file in OnJobStart');
} 

Link to comment
Share on other sites

I'm not sure I understand from everything that you posted exactly what the error is, or which file works and which doesn't, but this doesn't look right:

 
bikesDF = new ExternalDataFileEx('c:\bikes.txt', '\t');
purchasesDF = new ExternalDataFileEx('c:\purchases.txt', '\t');

The backslash \ is an escape character in JavaScript:

https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Literals#String_Literals

 

So, when you're specifying Windows path names in JavaScript string literals, you either need to double up the backslashes, so that the JavaScript interpreter treats the second one as a literal backslash, or use forward slashes, which get treated literally by JavaScript and as backslashes by modern versions of Windows.

 

So, try either this:

bikesDF = new ExternalDataFileEx('c:\\bikes.txt', '\t');

Or this:

bikesDF = new ExternalDataFileEx('c:/bikes.txt', '\t');

Link to comment
Share on other sites

So, try either this:

bikesDF = new ExternalDataFileEx('c:\\bikes.txt', '\t');

Or this:

bikesDF = new ExternalDataFileEx('c:/bikes.txt', '\t');

 

That's interesting because the purchases.txt file works absolutely brilliantly in a different (but very similar rule), but the bikes.txt file does not.... I'll give this a try and let you know.

 

Also: I'm not getting any error message. The JS is validating, but I'm not generating a table. It appears that bikesDF.FindRecord("member_id", matchBID); is returning a -1 value and throwing the whole thing off.....

Link to comment
Share on other sites

Updated the paths to the externalDF but I'm still running into a problem and my best guess is that it's because bikesDF.FindRecord("member_id", matchBID); is returning -1. matchBID is being properly assigned but as soon as I get into the loop it breaks because recordWalker isn't being properly setup. I'm pulling my hair out. Should I attach all of the relevant files?
Link to comment
Share on other sites

That's interesting because the purchases.txt file works absolutely brilliantly in a different (but very similar rule), but the bikes.txt file does not.... I'll give this a try and let you know.

Well, not every combination of a backslash followed by a letter is a valid escape sequence, so some of them just end up resolving to the trailing letter, without the backslash. In fact, at the link I posted earlier, there's a table of all the escape sequences, and you can see that '\b' resolves to a backspace character, while '\p' is not a valid escape, and therefore simply returns the letter 'p'. You can easily see this if you make a rule like so and click Validate:

return "X\b\pX";

The backslash will look like some strange character, but the 'p' will show up fine.

 

So what really happened with 'c:\purchases.txt' is that it stripped out the backslash and returned [noparse]"c:purchases.file"[/noparse]. In Windows, if you specify just a drive letter and a file name, you'll get a file in the current working directory on that volume, so you were really just lucky that it worked at all.

 

My recommendation to eliminate this entire realm of problems is to simply specify the file name, without any path specification, in your rule, and then either keep the external data file in the same folder as your other job files, or specify its location in the Search Path box on the Advanced tab of the Composition Settings dialog.

Also: I'm not getting any error message. The JS is validating, but I'm not generating a table. It appears that bikesDF.FindRecord("member_id", matchBID); is returning a -1 value and throwing the whole thing off.....

Yes, -1 is the expected returned value from ExternalDataFileEx.FindRecord if the specified value is not found (or if the file is not valid). If the value matches the field name in the first row (the "header" row), then it will return zero. Otherwise, it will return the one-based index of the first row (record) containing the specified value for that field.

 

So, you'll need to account for the possibility that the value is not found. You should be getting a message from where you test the .valid property.

 

A couple of other things that I noticed about your coding style, which won't necessarily make the rule work any better or worse, but since I'm here anyway:

 

You don't need to compare Boolean values to true. For instance, instead of this:

if(FusionPro.Composition.isPreview == true || FusionPro.inValidation == true)

Just do this:

if (FusionPro.Composition.isPreview || FusionPro.inValidation)

And instead of this:

if(bikesDF.valid != true)

I find this more readable:

if(!bikesDF.valid)

Link to comment
Share on other sites

Updated the paths to the externalDF but I'm still running into a problem and my best guess is that it's because bikesDF.FindRecord("member_id", matchBID); is returning -1. matchBID is being properly assigned but as soon as I get into the loop it breaks because recordWalker isn't being properly setup. I'm pulling my hair out. Should I attach all of the relevant files?

Well, I don't really want to just write the code for you. But you don't have to pull your hair out in frustration either, and you certainly don't have to guess. You can approach this logically and isolate the problem with some simple debugging techniques.

 

The first thing I would try is to just add a simple "return recordWalker" statement after the initialization of the recordWalker variable, so that you can click Validate and see what its value is. Or you can call Print(recordWalker), compose the job, and look in the log file.

 

Now, if, as we both suspect, the value is -1, then the value you're looking for is simply not being found. Or the file is not valid. I would test for all of these conditions and report an appropriate error. Something like this:

if (!bikesDF.valid)
 return "ExternalDataFileEx bikesDF not loaded";

var matchBID = Field("id");

var recordWalker = bikesDF.FindRecord("member_id", matchBID);
if (recordWalker < 1)
 return "Could not find value \"" + matchBID + "\" in external data file."

Exactly how to properly handle the case where you don't find the value you're looking for is a something you'll have to decide based on the requirements of the job.

Link to comment
Share on other sites

Thank you. Your explanation on the values being returned is going to be very helpful.

 

This is my first day writing JS and I've just finding reference materials and playing trial + error all day to make it work. It's just really odd to me that the first rule I wrote worked out wonderfully and this one (which is actually simpler) is proving to be a problem. I'll keep you updated.

Link to comment
Share on other sites

Thank you. Your explanation on the values being returned is going to be very helpful.

 

This is my first day writing JS and I've just finding reference materials and playing trial + error all day to make it work. It's just really odd to me that the first rule I wrote worked out wonderfully and this one (which is actually simpler) is proving to be a problem. I'll keep you updated.

Trial and error is fine, but if you're going to be a successful programmer, at any level, and in any language, then you need to know how to use some deductive reasoning to isolate and analyze problems, instead of just guessing and throwing stuff at the wall and seeing what sticks. And just like in real life, sometimes what seems simple is harder than you thought, and what seems hard is actually pretty easy, especially once you know a few basics.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...