Thursday, March 20, 2014

Barcode on a SSRS Report

Recently I was tasked with adding a barcode to the SalesPackingSlip report.  I had never done a barcode before so I wasn't really sure how this would turn out.

To help me out, I used WMSPickingList_OrderPick as an example.

The first thing we want to do here is create some parameters for the CustFormLetterDocument and the corresponding form. You can get to this form by going Accounts receivable -> Setup -> Forms -> Form setup.  We want to add 2 parameters to the Packing slip section.

As you can see I have added two parameters.  One is the 'Bar code setup', which contains the Font, Font size, and other information that will help the report display the bar code the way you want.  The other is just in case the customer would like to not display the barcode on the report.

The next thing we want to do is add some fields to our SalesPackingSlipHeaderTmp.  I picked the Header tmp table because my barcode will be the PackingSlipId which will, of course, be in the header.
Add the following fields:

  BarCode of type BarCodeString
  BarcodeFontName of type FontName
  BarcodeFontSize of type FontSize

I think the BarCodeString field is obvious, but why the other two?  Well, we want to be able to get the information from the BarCode setup.  So, if the customer wants to change the barcode font or size, the report doesn't have to be changed.

Now we need to modify some code.  The SalesPackingSlipDP class is where we will do all these modifications.  First we start by declaring some class level variables:

    BarcodeSetupId                      barcodeSetupId;
    BarcodeSetup                         barcodeSetup;
    Barcode                                 barcode;
    NoYes                                   showBarcode;

As we use these variables, I will explain what they are used for.
First, we are going to create a method to initialize these variables.

private void initBarcode()
    showBarcode     = CustFormletterDocument::find().showPackingSlilpIdBarCode;
    barcodeSetupId  = CustFormletterDocument::find().barcodeSetupId;
    barcodeSetup    = BarcodeSetup::find(barcodeSetupId);
    barcode         = BarcodeSetup.barcode();

As you can see here, we are getting the two parameters spoken of earlier.  Then we are using that barcodeSetupId parameter to get all the barcodeSetup information.  As you will see later, this will contain our FontSize and FontName.
The next method we want will actually get the text we want and convert it to a barcode.

private BarCodeString barCode()
    str barCodeContents = custPackingSlipJour.PackingSlipId;

    if (!barCodeContents)
        return '';

    if (barcodeSetup.validateBarcode(strUpr(barCodeContents)))
        throw(error(strFmt("@SYS41409", barcode.barcodeType(), strUpr(barCodeContents))));

    if (!barcode)
        return '';

    return barcode.barcodeStr();

Here we are checking to see if there is actual text to encode and then using the barcodeSetup to validate that the text we are trying to encode, fits the criteria in the barcodeSetup (such as Maximum/Minimum length). Then we simply return the barcode string.

The rest is pretty easy!  In our ProcessReport method of the DP class, we should call 'this.initBarcode()' and in our setSalesPackingSlipHeaderTmp we should have the following:

if (showBarcode == NoYes::Yes)
        salesPackingSlipHeaderTmp.barCode                    = this.barcode();
        salesPackingSlipHeaderTmp.barcodeFontName            = barcodeSetup.fontName;
        salesPackingSlipHeaderTmp.barcodeFontSize            = barcodeSetup.fontSize;

This will only add the barcode if the showBarcode box is checked in the parameters.

The only thing left to do is in visual studio.  
Add a new textbox and set it to use the barCode field you added to the HeaderTmp table.
The only tricky part here is using an expression for your FontName and FontSize.

For FontName, simply go in and add the field as an expression.  Very straight forward.
For FontSize, however, you need to do it a little different.  Go into the FontSize and add an expression, except you will need to encapsulate your field in the Cstr() method along with adding + "pt" + at the end.  This will make the 25pt that the report needs.  Here is an example:

That's it.  Not as difficult as I thought it was going to be, however, there were several new concepts that I had to learn.

Re-print a packing slip

The other day I was working on the SalesPackingSlip report and I didn't want to constantly be packing orders to be able to test it.  

If you go to Sales and marketing -> Inquiries -> Journals -> Packing slip you can see all the Packing slip journals and simply Re-print them!

I actually added a barcode to this report and will be explaining that in my next post later today.

Wednesday, March 12, 2014

Images only print on first Cheque

I received an e-mail from a customer on the Cheque_US report that I had modified.  For some reason, it was printing the CompanyLogo and Signatures on the first check but not the subsequent checks.

To print multiple checks you can go to Accounts Payable -> Journals -> Payments -> Payment journal -> Lines. Make sure your journal has multiple lines and you can use Functions -> Generate payments.

In looking at the code, I found that the ChequeDP class was causing the issue.  
*Note:  Whenever I have strange issues with reports, I always check the DP (DataProvider) class first to see if I can find out what is going on.

Anyway, continuing on... IN the ChequeDP class we find a method 'addImagesToFirstRow' that will add the images to your Tmp table.  The problem here is that in the 'insertChequePrintout' method (Line 74), it checks to see if this has already been done.  If it has, it won't do it again.  Hence the dilemma of only printing CompanyLogo/Sigs on the first check.

This is standard AX functionality and I believe it has to do with voided checks... You print the first check and then subsequent checks are voided so you don't want the logo / sigs on it?  I'm not 100% sure on the reasoning for this, however, if I do find a concrete answer I will update this post.

Monday, March 10, 2014

Phantom extra line on SSRS Report

I was working on the SalesInvoice report the other day.  I added a line to the SalesLine section that would display 'Notes' that have been attached to the Sales Line.  All the sales lines would print their note just fine except for the last one and I couldn't figure out why that would be.
Instead of wasting as lot of time and potentially not figuring out the 'why', I decided to simply set the Row Visibility property on the tablix row.

Simply right-click the row and select Row Visibilty.

The next screen is where you will set your expression!

Just make sure that the expression you use is a boolean expression and you are good to go!