vrijdag 19 september 2008

Refreshing a parent window when crmForm.IsDirty

When you try to refresh the parent window from an ISV page and the crmForm was
modified but not saved, you will get a confirmation dialog from CRM asking you
to continue or cancel the action.

To disable this behaviour you can Save the CRM form before the refresh action.

This seems to be standard CRM behaviour. You can try this when modifying an
account and then deactivating it. The new values will be saved automatically and
the account will be deactivated.

Put the following code in the OnInit of the aspx page:

protected override void OnInit(EventArgs e)
{
// Check if the crmForm was modified.
Response.Write("<script>" + "\n");
Response.Write("if (window.dialogArguments.document.crmForm.IsDirty == true)" + "\n");
Response.Write("{" + "\n");

Response.Write(" window.dialogArguments.crmForm.Save();" + "\n");
Response.Write("}" + "\n");
Response.Write("</script>;");

base.OnInit(e);
}

Regards,

Kenny

woensdag 20 augustus 2008

Hidden buttons reappear when resizing a crmForm

In a previous post I described how to hide custom buttons in a toolbar.
When a CRM form is resized by the user it appear that these hidden buttons will show up again.

To avoid this behaviour you should put your code into a global function and attach this function to the resize event of the window.

Example:

This code should be placed in the onload of the form.

HideButton = function()
{
var ULListItems = document.getElementById("mnuBar1").rows[0].cells[0].getElementsByTagName("UL")[0].getElementsByTagName("LI");
for(var i=0; i -1)
{
ULListItems[i].style.display = "none";
}
}
}

// Execute the function when loading the form
HideButton();

// Execute the function when the form is resized.
window.onresize = HideButton;

maandag 30 juni 2008

Read-Only fields don't get saved in the database.

When changing the value of a read-only field with JavaScript the new value will not be saved into the database.

To save the newvalue set the ForceSubmit property of the field to true.

crmForm.all.new_customfield.ForceSubmit = true;

Not the new value will also be saved into the database.

woensdag 25 juni 2008

Navision Application Server does not start: The Breakpoints already exists.

Sometimes a NAS tends to hang when there are breakpoints present in the database.

The following message will be displayed in the event viewer:

The Breakpoints already exists.

Identification fields and values:
Object ID='50001',Object Type='Form',Trigger Line='4',Code No='7'

To avoid this message you can simply delete all the breakpoints in NAV before running the NAS.

You can do this in either the object that is run by the specific NAS or in the NASHandler trigger of codeunit 1.

Simply add a line like "recBreakpoint.DELETEALL" where recBreakpoint points to a Record variable of the virtual Breakpoint table.

vrijdag 13 juni 2008

SELECTSTR limitations in NAV

There is a function in NAV that enables you to retrieve a string at a certain position in a comma seperated string.

There are a few limitations to this functions.
  1. You are foreced to use a comma ','
  2. You cannot use the same string twice in the same comma seperated string



From the NAV help file:
Comments
SELECTSTR treats string values as OPTIONS. This
means that identical values in different strings are not allowed.


A simple solution can be found on mibuso. Using this function removed both limitations as you can specifiy which seperation value to use.



fctGetFieldContent(pFieldNo : Integer;pText : Text[1024]) : Text[1024]
// ******************************************************************* //
// Code From Mibuso: //
// http://www.mibuso.com/forum/viewtopic.php?t=1429&highlight=strset //
// ******************************************************************* //

ReturnString := '';
FieldsFound := 1;
boo := -1;
REPEAT
CounterPos += 1;
IF pText[CounterPos] = '"' THEN
boo *= -1
ELSE BEGIN
IF (pText[CounterPos] = ',') AND (boo = -1) THEN
FieldsFound += 1
ELSE
IF FieldsFound = pFieldNo THEN
ReturnString := ReturnString + COPYSTR(pText,CounterPos,1);
END;
UNTIL (CounterPos = STRLEN(pText)) OR (FieldsFound > pFieldNo);

EXIT(ReturnString);



NOTE: You could also pass the seperation string to the function and replace the line IF (pText[CounterPos] = ',') AND (boo = -1) THEN with IF (pText[CounterPos] = pSerperator) AND (boo = -1) THEN

All credits go to PrebenRasmussen who posted this on Mibuso.

donderdag 12 juni 2008

Hiding custom buttons in CRM 4.0 Toolbar

In CRM 3 it was possible to hide a button on a toolbar just by calling the document.getElementById("").style.display = "none" method.

This will NOT work in CRM 4.0. The ID of the button seems to be generated when the CRM Form is loaded. One time it might be ISV_New_1_MyButtonID the other time it might be ISV_New_39_MyButtonID.

A simple workarround is by checking all the LI items in the UL of the MenuBar and by comparing its ID with "MyButtonID".
To do so use the following javascript in the forms OnLoad event:



var ULListItems = document.getElementById("mnuBar1").rows[0].cells[0].getElementsByTagName("UL")[0].getElementsByTagName("LI");
for(var i=0; i -1)
{
ULListItems[i].style.display = "none";
}
}

woensdag 4 juni 2008

Putting a DateTime value in a CrmDateTime field

When you want to assign a DateTime value to a CrmDateTime field while using the Webservice API it is not as simple as converting the DateTime field to a string and assigning the value.

The string has to be in a specific format.

Example:
CrmDateTime sEndDate = new CrmDateTime(MyDateTimeValue.ToString());

The above will NOT work.
Format the DateTime with the following format.

CrmDateTime sEndDate = new CrmDateTime(MyDateTimeValue.ToString("s"));

maandag 2 juni 2008

Intercompany Invoicing

I came accros this nice feature of NAV while implementing some IC changes for a customer.

I wanted to send a Purchase Order from one company to the other. At the end of the whole IC process I ended up with TWO purchase documents in the first company.


After logging a support call it seemed this behaviour is by design. MS suggests the following solution.


Add a warning message when posting the originating Purchase Order.
Add a warning message when processing the IC inbox.

What you could also do in my opinion, is try and delete the originating purchase order when the invoice creating is completed.

Steps to reproduce in standard CRONUS database.

Open Company A:
Step 1: Create a purchase order in Company A
Step 2: Go to functions > Send IC Purchase Order
Step 3: Go to Financial Management > Intercompany Postings > Outbox Transactions
Step 4: Set the line action to "Send to IC Partner" (F9)
Step 5: Complete the line actions (F11)

Open Company B:
Step 6: Go to Financial Management > Intercompany Postings > Inbox Transactions
Step 7: Set the line action to "Accept" (F9)
Step 8: Complete the line actions (F11)
Step 9: Ship & Invocie the newly created Sales Invoice
Step 10: Go to Financial Management > Intercompany Postings > OutboxTransactions
Step 11: Set the line action to "Send to IC Partner" (F9)
Step 12: Complete the line actions (F11)

Open Company A:
Step 13: Go to Financial Management > Intercompany Postings > Inbox Transactions
Step 14: Set the line action to "Accept" (F9)
Step 15: Complete the line actions (F11)

Result:
The system now has created a new purchase invoice in company A.
We now have 2 purchase documents in company A and 1 sales document in company B.


Fix from MS:

CodeUnit 90: Putch-Post
Insert the follwing code in Cod90 function OnRun:

.............

CopyAndCheckDocDimToTempDocDim;

Vend.GET("Buy-from Vendor No.");
Vend.CheckBlockedVendOnDocs(Vend,TRUE);
IF "Pay-to Vendor No." <> "Buy-from Vendor No." THEN BEGIN
Vend.GET("Pay-to Vendor No.");
Vend.CheckBlockedVendOnDocs(Vend,TRUE);
END;

//NEW CODE BEGIN

IF "Send IC Document" AND
("IC Direction" = "IC Direction"::Outgoing) AND
("Document Type" IN ["Document Type"::Order,"Document Type"::"Return Order"]) THEN
IF NOT CONFIRM(Text051) THEN EXIT;

//NEW CODE END


IF Invoice THEN BEGIN
PurchLine.RESET;
PurchLine.SETRANGE("Document Type","Document Type"); PurchLine.SETRANGE("Document No.","No.");
........





Add the following TextConstant:
Text051:
This is an IC document. If you post this document and the invoice you receive from your IC partner, it will result in duplicate postings.\Are you sure you want to post this document?

In table 418 IC Inbox Transaction
Add the folling code at the end of function InboxCheckAccept:




IF ("Source Type" = "Source Type":: "Purchase Document") AND
("Document Type" = "Document Type"::Invoice)
THEN BEGIN
ICInboxPurchHeader.GET("Transaction No.","IC Partner Code","Transaction Source");
IF ICInboxPurchHeader."Your Reference" <> '' THEN BEGIN
PurchHeader.SETRANGE("No.",ICInboxPurchHeader."Your Reference");
IF PurchHeader.FINDFIRST THEN
MESSAGE(Text003,ICInboxPurchHeader."IC Transaction No.",ICInboxPurchHeader."Your Reference")
ELSE BEGIN
PurchInvHeader.SETCURRENTKEY("Order No.");
PurchInvHeader.SETRANGE("Order No.",ICInboxPurchHeader."Your Reference");
IF PurchInvHeader.FINDFIRST THEN
IF NOT CONFIRM(Text004,TRUE,ICInboxPurchHeader."Your Reference",ICInboxPurchHeader."IC Transaction No.") THEN
"Line Action" := xRec."Line Action"
END;
END;
END;

and add the following text constants:

Text003 :
A purchase order already exists for transaction %1. If you accept and post this document, you should delete the original purchase order %2 to avoid duplicate postings.

Text004:
Purchase invoice %1 has already been posted for transaction %2. If you accept and post this document, you will have duplicate postings.\Are you sure you want to accept the transaction?
Target Files

Disable fields in a Bulk Edit form

To disable a field in a Bulk edit form you would think editing the form's OnLoad event would do the trick.

Something like
if (crmForm.FormType == 6)
{
crmForm.new_myfield.style.display = "none";
}


This will NOT work.

No Javascript what soever is triggered in the bulk editform.

So to disable a field in a bulk edit form just enable the fields onchange event of the form.

Values of ASP.NET Controls are cleared on postback

I came accros this issues when I was trying to export a gridview that I made to excel. When I pressed my "Export To Excel" button on my custom ASPX page the gridview turned to null.

To be able to re-use data in an ASP.NET control after doing a postback, the EnableViewState property of the control and the page must be set to true.

When you create a new ASP.NET page this is the case by default. Except when you deploy this page to MS CRM 4.0 it is likely your code will not work as you excpected because MS CRM 4.0 disables the viewstate of all it’s pages in it’s web.config file.

To avoid this issue be sure to enable the viewstate in your custom page.

Example:

< %@ Page Language="C#" AutoEventWireup="true" CodeFile="MyPage.aspx.cs"    Inherits="MyPage" EnableViewState="true % >


Convert a Navision Filter to a SQL Where clause

I wrote this SQL script a while ago.
It will convert most of the Navision filters into a SQL WHERE clause.

@ will be converted to lower(..)
* will result in a LIKE %
.. will result in a BETWEEN clause
& = AND
= OR
<> = NOT

Also brackets are supported.

To use this script you should pass the fieldname and the filter to this function.


set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

-- ===============================================================
-- Author: Kenny Vaes
-- Create date: 19/03/2007
-- Description: Converts a Navision Filter to a SQL Where clause
-- ===============================================================

ALTER FUNCTION [dbo].[CONVERT_NAV_FILTER]
(
-- Add the parameters for the function here
@parFieldName VARCHAR(MAX),
@parFilter VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @CurrentStringPOSPoints INT
DECLARE @CurrentStringPOSPipe INT
DECLARE @CurrentStringPOSAmp INT
DECLARE @CurrentStringPOSAt INT
DECLARE @CurrentStringPOSNot INT
DECLARE @CurrentStringPOSHaakOpen iNT
DECLARE @CurrentStringPOSHaaksluit int
DECLARE @CurrentStringPOSStar int

DECLARE @From VARCHAR(MAX)
DECLARE @To VARCHAR(MAX)
Declare @IndexToRead INT
Declare @ObjectToRead INT
Declare @IndexRead INT
Declare @ObjectRead INT
DECLARE @NextIndexToRead INT
Declare @NextObjectToRead INT
DECLARE @FirstRun INT


DECLARE @ReturnValue VARCHAR(MAX)

SET @ReturnValue = ''
SET @IndexToRead = 0
SET @CurrentStringPOSPoints = 0
SET @CurrentStringPOSPipe = 0
SET @CurrentStringPOSAmp = 0
SET @CurrentStringPOSAt = 0
SET @CurrentStringPOSNot = 0
SET @CurrentStringPOSHaakOpen = 0
SET @CurrentStringPOSHaaksluit = 0
SET @ObjectToRead = 0
SET @IndexRead = 0
SET @FirstRun = 1
WHILE 1 = 1
BEGIN

SET @NextIndexToRead = LEN(@parFilter)
SET @IndexToRead = LEN(@parFilter)
SET @ObjectToRead = 0
SET @NextObjectToRead = 0

--Find the index to read
IF @IndexToRead >= Charindex('..', @parFilter, @IndexRead + 1) and (Charindex('..', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex('..', @parFilter, @IndexRead+1)
SET @ObjectToRead = 1
END
IF @IndexToRead >= Charindex('', @parFilter, @IndexRead + 1) and (Charindex('', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex('', @parFilter, @IndexRead+1)
SET @ObjectToRead = 2
END

IF @IndexToRead >= Charindex('&', @parFilter, @IndexRead + 1) and (Charindex('&', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex('&', @parFilter, @IndexRead+1)
SET @ObjectToRead = 3
END

IF @IndexToRead >= Charindex('<>', @parFilter, @IndexRead + 1) and (Charindex('<>', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex('<>', @parFilter, @IndexRead+1)
SET @ObjectToRead = 5
END

IF @IndexToRead >= Charindex('(', @parFilter, @IndexRead + 1) and (Charindex('(', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex('(', @parFilter, @IndexRead +1)
SET @ObjectToRead = 6
END

IF @IndexToRead >= Charindex(')', @parFilter, @IndexRead + 1) and (Charindex(')', @parFilter, @IndexRead + 1) > 0)
BEGIN
SET @IndexToRead = Charindex(')', @parFilter, @IndexRead +1)
SET @ObjectToRead = 7
END

-- Find the next index to read
IF @NextIndexToRead >= Charindex('..', @parFilter, @IndexToRead + 1) and (Charindex('..', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex('..', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 1
END
IF @NextIndexToRead >= Charindex('', @parFilter, @IndexToRead + 1) and (Charindex('', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex('', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 2
END

IF @NextIndexToRead >= Charindex('&', @parFilter, @IndexToRead + 1) and (Charindex('&', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex('&', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 3
END

IF @NextIndexToRead >= Charindex('<>', @parFilter, @IndexToRead + 1) and (Charindex('<>', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex('<>', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 5
END

IF @NextIndexToRead >= Charindex('(', @parFilter, @IndexToRead + 1) and (Charindex('(', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex('(', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 6
END

IF @NextIndexToRead >= Charindex(')', @parFilter, @IndexToRead + 1) and (Charindex(')', @parFilter, @IndexToRead + 1) > 0)
BEGIN
SET @NextIndexToRead = Charindex(')', @parFilter, @IndexToRead+1)
SET @NextObjectToRead = 7
END

-- *********************************************
-- Checks Complete start converting
-- *********************************************


-- If this is the first time the conversion is done and there is a or & sign,
-- Set a filter on the first part

IF @FirstRun = 1 and @IndexToRead > 1
BEGIN
IF @ObjectToRead = 2 --
BEGIN
SET @From = Substring(@parFilter, 1, @IndexToRead - 1)

if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''') OR '
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''') OR '
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''') OR '
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''') OR '

END
IF @ObjectToRead = 3 -- &
BEGIN
SET @From = Substring(@parFilter, 1, @IndexToRead - 1)

if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''') AND '
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''') AND '
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''') AND '
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''') AND '

END

END
SET @FirstRun = 0


IF @ObjectToRead = 1 -- 1 = ..
BEGIN
SET @From = Substring(@parFilter, @IndexRead + 1, @IndexToRead - (@IndexRead + 1))

IF @nextobjecttoread = 0
SET @To = substring(@parFilter, @IndexToRead + 2 , @NextIndexToRead -(@IndexToRead + 1))
else
SET @To = substring(@parFilter, @IndexToRead + 2 , @NextIndexToRead -(@IndexToRead + 2))

if charindex('@', @From, 0) > 0 or charindex('@', @To, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') BETWEEN ''' + lower(replace(@From, '@', '')) + ''' AND ''' + lower(replace(@To,'@','')) + ''')'
ELSE
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' BETWEEN ''' + @From + ''' AND ''' + @To + ''')'

IF @NextObjectToRead = 2 --
SET @ReturnValue = @ReturnValue + ' OR '

IF @NextObjectToRead = 3 -- &
SET @ReturnValue = @ReturnValue + ' AND '
END

IF @ObjectToRead = 2 -- 2 =
BEGIN

IF @NextObjectToRead <> 6 and @NextObjectToRead <> 5 and @NextObjectToRead <> 1
BEGIN
if @NextObjectToRead = 0
SET @From = substring(@parFilter, @IndexToRead + 1, @NextIndexToRead - @IndexToRead)
else
SET @From = substring(@parFilter, @IndexToRead + 1, @NextIndexToRead - (@IndexToRead + 1))

if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''')'
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''')'
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''')'
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''')'
END

IF @NextObjectToRead = 2 --
SET @ReturnValue = @ReturnValue + ' OR '

IF @NextObjectToRead = 3 -- &
SET @ReturnValue = @ReturnValue + ' AND '
END

IF @ObjectToRead = 3 -- 3 = &
BEGIN

IF @NextObjectToRead <> 6 and @NextObjectToRead <> 5 and @NextObjectToRead <> 1
BEGIN
if @NextObjectToRead = 0
SET @From = substring(@parFilter, @IndexToRead + 1, @NextIndexToRead - @IndexToRead)
else
SET @From = substring(@parFilter, @IndexToRead + 1, @NextIndexToRead - (@IndexToRead + 1))

if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%') , '@', '')) + ''')'
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''')'
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''')'
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''')'
END

IF @NextObjectToRead = 2 --
SET @ReturnValue = @ReturnValue + ' OR '

IF @NextObjectToRead = 3 -- &
SET @ReturnValue = @ReturnValue + ' AND '
END

IF @ObjectToRead = 4 -- 4 = @
BEGIN
SET @ReturnValue = @ReturnValue
END

IF @ObjectToRead = 5 -- 5 = <>
BEGIN
SET @ReturnValue = @ReturnValue + ' NOT '

SET @From = substring(@parFilter, @IndexToRead + 2, @NextIndexToRead - (@IndexToRead + 2))

if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''')'
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''')'
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''')'
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''')'

IF @NextObjectToRead = 2 --
SET @ReturnValue = @ReturnValue + ' OR '

IF @NextObjectToRead = 3 -- &
SET @ReturnValue = @ReturnValue + ' AND '
END

IF @ObjectToRead = 6 -- 6 = (
BEGIN
SET @ReturnValue = @ReturnValue + '('

SET @From = Substring(@parFilter, @IndexToRead + 1, @NextIndexToRead - (@IndexToRead +1))

IF @NextObjectToRead = 2 --
BEGIN
if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''') OR '
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''') OR '
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''') OR '
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''') OR '

END
IF @NextObjectToRead = 3 -- &
BEGIN
if charindex('@', @From, 0) > 0
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@From, '*', '%'), '@', '')) + ''') AND '
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@From, '@', '')) + ''') AND '
else
if charindex('*', @From, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@From, '*', '%') + ''') AND '
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @From + ''') AND '
ENd
END

IF @ObjectToRead = 7 -- 7 = )
BEGIN
SET @ReturnValue = @ReturnValue + ')'

IF @NextObjectToRead = 2 --
SET @ReturnValue = @ReturnValue + ' OR '

IF @NextObjectToRead = 3 -- &
SET @ReturnValue = @ReturnValue + ' AND '
END

IF @ObjectToRead = 8 -- 8 = *
BEGIN
SET @ReturnValue = @ReturnValue
END

-- Nothing found? => BREAK loop
IF @IndexToRead = LEN(@parFilter)
BREAK

SET @ObjectRead = @ObjectToRead
SET @IndexRead = @IndexToRead
SET @IndexToRead = @NextIndexToRead

END -- LOOP

IF @ReturnValue = ''
BEGIN
if charindex('@', @parFilter, 0) > 0
if charindex('*', @parFilter, 0) > 0
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') LIKE ''' + lower(replace(replace(@parFilter, '*', '%'), '@', '')) + ''')'
else
SET @ReturnValue = @ReturnValue + '(lower(' + @parFieldName + ') = ''' + lower(replace(@parFilter, '@', '')) + ''')'
else
if charindex('*', @parFilter, 0) > 0
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' LIKE ''' + replace(@parFilter, '*', '%') + ''')'
else
SET @ReturnValue = @ReturnValue + '(' + @parFieldName + ' = ''' + @parFilter + ''')'
END


-- Return the result of the function
RETURN '(' + @ReturnValue + ')'
END

donderdag 22 mei 2008

Hide lookup fields on a crmForm

Hiding a field and caption can normally be done by setting the display property of the control to none.

Example:
crmForm.all.new_customfield.style.display = "none";
crmForm.all.new_customfield_c.style.display = "none";

The _c extensions specifies the caption of the field.
In case of a lookupfield the above code won't work bacause the "new_customfield" points to the lookup button and not the textbox.

Another way to hide fields and captions it to hide the TD tag that is wrapped arround it. This will work for all types of fields.

Example:
crmForm.all.new_customfield_d.style.display = "none";
crmForm.all.new_customfield_c.style.display = "none";

_d meaning the data field (the textbox) and _c meaning caption.

Enjoy!!

Executing client side script when an associated entity is added

It is sometimes required to capture the event when an associated entity is added. This event cannot be captured in a "supported way".

To do so we first have to load the associated view to make sure the object is available. After it is loaded we can retrieve the crmGrid object that is located inside the IFRAME. Attach a function to the onrefresh event of this control and you can start doing you coding.
Call a webservice to do some async calls or just update some fields on the CRM form.

Add this code to the OnLoad of the CRM form. Make sure you also replace the control names with your own controls. (You can easily find them using the IE Developer Toolbar)


//=========================================================================
// Author: Kenny Vaes
// Creation date: 22/05/2008
// Description: Execute client side code when an associated entity is added
//=========================================================================

try
{
var script = document.createElement("script");
script.language = "javascript";
document.getElementsByTagName('head')[0].appendChild(script);

// Create a function that will execute when the gridview of the associated entity refreshes
var GridRefresh = function()
{
var AssocGridBody = document.getElementById("areametris_incident_assetFrame").contentWindow.document.getElementById("gridBodyTable");
if (AssocGridBody)
{
var CurrentRowCount = AssocGridBody.getElementsByTagName('tr').length;

// If the current rowcount = 1 it is possible that there is no data in the grid
// In this case the grid will only contain 1 colomn

if (CurrentRowCount == 1)
{
if (AssocGridBody.getElementsByTagName('tr')[0].getElementsByTagName('td').length == 1)
{
CurrentRowCount = 0;
}
}

if (CurrentRowCount > PreviousRowCount)
{
PreviousRowCount = CurrentRowCount;
// Do Stuff...
}
}
}

//Create a function that executes after the form has loaded.
var FormLoaded = function()
{
if ((event.srcElement.readyState == "complete") (event.srcElement.readyState == "loaded")) {
var menubuttonassets = document.getElementById("navmetris_incident_asset");
if (menubuttonassets)
{
// Perform a click to open the associated view in the iframe
menubuttonassets.click();

// Set the focus back to the area screen.
loadArea('areaForm');

}

var assocView = document.getElementById("areametris_incident_assetFrame");
if (assocView)
{
// Add an event to the readystate change of the iframe
assocView.onreadystatechange = function ()
{
if (assocView.readyState == "complete")
{
// Get the gridview inside the iframe and attach an event.
var crmGridAssets = assocView.contentWindow.document.getElementById("crmGrid");
if (crmGridAssets)
{
// Attach a function to the onrefresh of the grid
crmGridAssets.attachEvent("onrefresh", GridRefresh);
var AssocGridBody = document.getElementById("areametris_incident_assetFrame").contentWindow.document.getElementById("gridBodyTable");
if (AssocGridBody)
{
PreviousRowCount = AssocGridBody.getElementsByTagName('tr').length;
if (PreviousRowCount == 1) PreviousRowCount = 0;
}
}
}
}
}
}
}
script.attachEvent("onreadystatechange", FormLoaded);

} catch (e) { alert(e); }