I had a requirement to consume .PDFs and attach all of them that arrived within 30 minutes to an email with the PDFs as attachments.  I created a multi part message that I named msg_Email of type System.Xml.XmlDocument.  I created the message using a Construct Message shape.  I then loaded the body of the message using the .LoadXML() method.  I then used a helper class named EmailAttacher to attach the new messages needing to be attachments to the existing multi part email message.  Here is the helper class code.

namespace EmailAttacher
{
    public class MessageHelper
    {
        public static void AddAttachment(XLANGMessage destination, XLANGMessage attachment, string filename)
        {
            try
            {
                int count = destination.Count;
                destination.AddPart(attachment[0], string.Format(“Attachment_{0}”, count));
                destination[count].SetPartProperty(typeof(MIME.FileName), filename);
            }
            finally
            {
                //decrement reference count
                destination.Dispose();
                attachment.Dispose();
            }
        }

}

The message assignment shape has the following code to add the newest message to the existing message.

EmailAttacher.MessageHelper.AddAttachment(msg_Email, msg_ToAddAsAttachment,”NameOfAttachedFile”);

Don’t forget to add this, to ensure all message parts that aren’t the body are attachments.

msg_Email(SMTP.MessagePartsAttachments) = 2;

 

Every once in a while I need a little C# method to do some dirty work.  Here is an example of how to use Regular Expressions to match Windows style filemask matching.

private bool FitsMask(string fileName, string fileMask)
{
    string pattern =
         ‘^’ +
         System.Text.RegularExpressions.Regex.Escape(fileMask.Replace(“.”, “__DOT__”)
                         .Replace(“*”, “__STAR__”)
                         .Replace(“?”, “__QM__”))
             .Replace(“__DOT__”, “[.]“)
             .Replace(“__STAR__”, “.*”)
             .Replace(“__QM__”, “.”)
         + ‘$’;
    return new System.Text.RegularExpressions.Regex(pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase).IsMatch(fileName);
}

Here is the pure C# method of doing the same thing.

/// <summary>
/// Filemask can be “*|[*]filenamepart[*].*|[*]extpart[*]”
/// </summary>
/// <param name=”fileName” ></param>
/// <param name=”fileMask” ></param>
/// <returns>Boolean</returns>
/// <remarks>
/// Handles positional start and/or ending wildcards.
/// </remarks>
private bool FileMatchesMask(string fileName, string fileMask)
{
   const string asterisk = “*”;
   string se = string.Empty;
   if (fileMask.Equals(“*.*”))
      return true;

   // first, get comparable filenames and extensions
   string fn = Path.GetFileNameWithoutExtension(fileName).ToLower();
   string ext = Path.GetExtension(fileName).Replace(“.”, se).ToLower();

   string maskName = Path.GetFileNameWithoutExtension(fileMask).ToLower();
   string maskExt = Path.GetExtension(fileMask).ToLower().Replace(“.”, se);
   string maskExtStripped = maskExt.ToLower().Replace(asterisk, se);
   string maskNameStripped = maskName.ToLower().Replace(asterisk, se);
   wcPos fnWCP = GetWildCardPosition(maskName);
   wcPos extWCP = GetWildCardPosition(maskExt);

   if (maskExt.Equals(asterisk))
   {
     // ext can be anything, but fn may be masked
     if (maskName.IndexOf(asterisk) > -1)
     {
      // fn masked, ck position of wildcard
      switch (fnWCP)
      {
          case wcPos.wrap:
          return IsValueMatch(fn, maskNameStripped, wcPos.wrap);
          case wcPos.start:
          return IsValueMatch(fn, maskNameStripped, wcPos.start);
          case wcPos.@end:
          return IsValueMatch(fn, maskNameStripped, wcPos.@end);
          default:
          return IsValueMatch(fn, maskNameStripped, wcPos.wrap);
      }
     }
     else
     {
      // need exact match on filename, any ext is ok
      if (maskName.Equals(fn))
          return true;
     }
   }
   else if (maskName.Equals(asterisk))
   {
     // fn can be anything, but ext may be masked
     if (maskExt.IndexOf(asterisk) > -1)
     {
      // ext masked, ck position of wildcard
      switch (extWCP)
      {
          case wcPos.wrap:
          return IsValueMatch(ext, maskExtStripped, wcPos.wrap);
          case wcPos.start:
          return IsValueMatch(ext, maskExtStripped, wcPos.start);
          case wcPos.@end:
          return IsValueMatch(ext, maskExtStripped, wcPos.@end);
          default:
          return IsValueMatch(ext, maskExtStripped, wcPos.wrap);
      }
     }
     else
     {
      // need exact match on ext, any filename is ok
      if (maskExt.Equals(ext))
          return true;
     }
   }
   else
   {
     // here neither fn or ext = asterisk so must ck for
          // existence of asterisk in either
     // b/c of position of * this will get hairy…
     if (extWCP != wcPos.none)
     {
      // ext is masked, ck for masking in fn
      if (maskName.IndexOf(asterisk) > -1)
      {
          // ext and fn are masked
          return IsValueMatch(fn, maskNameStripped, fnWCP) &
                         IsValueMatch(ext, maskExtStripped, extWCP);
      }
      else
      {
          // fn not masked, look for fn exact match and
                  // ext masked
          if (fn.Equals(maskName) &&
                     IsValueMatch(ext, maskExtStripped, extWCP))
            return true;
      }
     }
     else
     {
      // ext is not masked, requires exact ext
               // and ck for fn masking
      if (maskName.IndexOf(asterisk) > -1)
      {
          // fn masked
          if (IsValueMatch(fn, maskNameStripped, fnWCP) &&
                     ext.Equals(maskExtStripped))
            return true;
          else if (fn.Equals(maskName) &&
                           ext.Equals(maskExtStripped))
            return true;
      }
     }
   }
   return false;
}

 

When trying to build a BizTalk project I got this error.  Here is the solution:

1) Checking out a single XSD file does not result in the corresponding CS file being created

2) Excluding the XSD file from the project then re-including it does result in the CS file being created

3) Checking out just the BTPROJ file and the XSD file (expecting this perhaps to be similar to the exclude / re-include) does not result in the corresponding CS file being created

As detailed above, checking out every file in the solution prior to build addresses the problem.

 

A funny sight I saw today:

BTSOnMac

 

I think they would be proud!

BillNSteve

 

I had an XSLT style sheet that used a C# method to return a multi line string.  I wanted it to include the HTML <BR></BR> tag ad specific places within the string but not as literals.  After some searching around I found that instead of trying to get the <BR></BR> tag to not be literal, I could simply use the <pre></pre> tag within my HTML and it would force it to recognize the “/r/n” returned from the C# method.

 

I needed to find the total purchase order amount given the quantity and line item price on an X12 850 using XSLT and .NET to transform XML into HTML.

In my case:

PO102 = Quantity

PO104 = Price

Add the following to the stylesheet declaration:

xmlns:msxsl=”urn:schemas-microsoft-com:xslt”

for example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var userCSharp" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp>">

In your XSLT use the following code, modifying the referenced node and element within your XML

<xsl:variable name="tmpTotal"> <total_amount> <xsl:for-each select="ns0:PO1Loop1"> <item> <xsl:value-of select="ns0:PO1/PO102 * ns0:PO1/PO104"/> </item> </xsl:for-each> </total_amount> </xsl:variable> <total> <!--<xsl:variable name="myTotal" select="msxsl:node-set($tmpTotal)"/>--> <xsl:variable name="myTotal" select="$tmpTotal"/> <xsl:value-of select="sum(msxsl:node-set($myTotal)/total_amount/item)" /> </total>

 

I needed to count all of the rows in an entire database.

I looked around and came up with a pretty easy way to do this.

Create this stored procedure and when you run it, it will display it for you.

create proc AllTableCount AS BEGIN /*Create temp table to populate the row counts for all of the tables*/ CREATE TABLE #TableRowCount( TableName sysname, [RowCount] int) /*Now actually get the counts*/ EXEC sp_MSforeachtable 'INSERT #TableRowCount (TableName,[RowCount]) SELECT ''?'',Count(*) from ?' /*Finally: sum up all of the counts and show it*/ Select SUM([RowCount]) as [Total Number Of Rows From Database] from #TableRowCount END

 

A recent friend asked me why he would be getting this error, and while debugging a splitting process, I came across this same error: hence this blog entry.

(not all of the time, but most of the time) What is going on is that the EDI data is being parsed by the EDI pipeline and resolving to a party, and I wanted to take a copy of that message and drop it to a folder so I can look at the claim to see what is really going on.

However when I assigned the data to the new message I simply sent it to the EDI assembler and assumed that it would create the EDI document and I could pass it along to the BA and they could tell me what needs to happen, yada yada yada.

All of the sudden I started getting these messages: Invalid character in data element.

What is actually going on is that when data is coming in, it is resolving to a particular party, but when going out, it does not have a party associated with it, so it defaults to the global party. The global party does not have a lot of the configuration options that are available to a defined party. One of those options are to allow decimals in EDI documents.

Here is what is in a defined party to get decimals to go in:

PartyValidationSettings

However, for the global party, the setting is not available.

This means that all data for a global party must be implicit decimal.

Change the following property to allow outbound decimals:

OutboundPartyValidationSettings

And in the orchestration, when you create the new message, make sure your code looks like this:

NewEDIMsg.MessagePart=EDIMsg.MessagePart;
NewEDIMsg(EDI.DestinationPartyName)=EDIMsg(MessageTracking.PartyName);

 

I wanted to enhance my previous blog entry about how to successfully split the EDI transactions into individual claims.

The one liner does not adequately do justice as to what is really going on, so I thought I would embellish on how to get it properly configured,  and how to make changes (if you really want to).

The first thing is to explain the fundamental difference between the the single and multiple schema:

The BizTalk EDI Pipeline implements splitting at two levels:

1.  An interchange with multiple transaction sets (ST) will be split at the transaction level

2.  Additional splitting is controlled by annotations in the schema

        subdocument_break=”yes” in an annotation at top of schema switches the additional splitting functionality ON.

        At the segment level where additional breaks should occur attribute, subdocument_creation_break=”yes” is used

With the introduction of BizTalk 2006 R2, the EDI pipeline applied a different splitting behavior to “Multiple” schemas than had been applied from previous versions of BizTalk Accelerator for HIPAA.  BizTalk 2006 R2 would split subdocuments as per the “subdocument_creation_break” attribute but it would also include extra/non-essential sibling subdocument data which caused the output XML to be bloated and the splitting of large EDI files extremely slow.

A design change (KB 967945) was created to address the errant BizTalk 2006 R2 splitting behavior.  This hot fix restored the original and expected splitting behavior enjoyed in previous versions of BizTalk Accelerator for HIPAA.  With the hot fix applied, one would have to edit the “Multiple” schema to add an additional splitting attribute at the top of the document.  The new attribute should appear just after the subdocument_break=”yes” attribute and read as:  Split_Without_Sibling_Data=”Yes”.  Split_Without_Sibling_Data=”Yes” enables the new and efficient splitting behavior for “Multiple” schemas.

This design change was also forwarded into BizTalk Server 2009, but was not present in the released product.  Rather it appeared as a hot fix rollup, KB973415.  The KB973415 BizTalk Server 2009 rollup fix contains the new HIPAA 005010 schemas and the fix for new splitting behavior.  Again after applying this rollup fix, one must still edit all desired “Multiple” schemas to add the attribute,  Split_Without_Sibling_Data=”Yes”.

The schemas are mostly the same, except for the subdocument_creation_break attribute in the annotation:

<!-- Multiple -->
<xs:element name="TS837Q3_2300_Loop">
<xs:annotation>
 <xs:appinfo>
   <b:recordInfo structure="delimited" delimiter_type="inherit_record" field_order="infix" count_ignore="yes" child_delimiter="default" subdocument_creation_break="yes" notes="Claim information" />
 </xs:appinfo>
</xs:annotation>

<!-- Single -->
<xs:element name="TS837Q3_2300_Loop">
<xs:annotation>
 <xs:appinfo>
   <b:recordInfo structure="delimited" delimiter_type="inherit_record" field_order="infix" count_ignore="yes" child_delimiter="default" notes="Claim information" />
 </xs:appinfo>
</xs:annotation>

One thing that is not documented (at least I could not find it), is that after you downloaded and applied the 5010 hot fix, you need to add the following attribute Split_Without_Sibling_Data to the root <xs:appinfo> element

<!-- Out of the box -->
<xs:appinfo>
 <schemaEditorExtension:schemaInfo namespaceAlias="btsedi" extensionClass="Microsoft.BizTalk.Edi.SchemaEditorExtension.EdiSchemaExtension" standardName="EDI" xmlns:schemaEditorExtension="http://schemas.microsoft.com/BizTalk/2003/SchemaEditorExtensions" />
 <b:schemaInfo subdocument_break="yes" BiztalkServerEditorTool_Version="1.5" root_reference="X12_00401_837_I" displayroot_reference="X12_00401_837_I" version="3.0" standard="EDI" standards_version="00401" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" X12ConditionDesignator_Check="Yes" />
</xs:appinfo>

<!-- After modification -->
<xs:appinfo>
 <schemaEditorExtension:schemaInfo namespaceAlias="btsedi" extensionClass="Microsoft.BizTalk.Edi.SchemaEditorExtension.EdiSchemaExtension" standardName="EDI" xmlns:schemaEditorExtension="http://schemas.microsoft.com/BizTalk/2003/SchemaEditorExtensions" />
 <b:schemaInfo subdocument_break="yes" Split_Without_Sibling_Data="yes" BiztalkServerEditorTool_Version="1.5" root_reference="X12_00401_837_I" displayroot_reference="X12_00401_837_I" version="3.0" standard="EDI" standards_version="00401" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" X12ConditionDesignator_Check="Yes" />
</xs:appinfo>

If you don’t manually modify the schema, you will end up with all of the members in the transaction with one claim in each message that is submitted to the message box. ‘Bloated XML’ as a friend of mine calls it.

This means that you are now empowered on how to make changes to the splitting behavior, you can take the subdocument_creation_break attribute and move it from the claim level (2300) and move it to the member level (2000) and BizTalk will split the claims by members with all of that members claims grouped together.

 

Wanted to share the demo that I created on the map conversion demo we have created. This demo converts an 834 map, but the product converts all of the HIPAA transactions.

Below is a video of the conversion tool in action, make sure you click the 720p resolution.

You can read more at the blog post about the HIPAA 4010 to 5010 map converter

© 2015 BizTalk Blog Suffusion theme by Sayontan Sinha