Unbundle doesn't include SE* segment?

May 14, 2013 at 5:42 PM
I'm trying to take a file and split it into separate files by loop 2300, essentially using the code below.

Is it valid to have an ST* but not a corresponding SE* or is there an issue with my code?

If I try to call AcknowledgeTransactions on the unbundled file, I get this error, but if I manually edit the file and add the SE* segment, I don't get the error.
System.IndexOutOfRangeException was unhandled
  HResult=-2146233080
  Message=Index was outside the bounds of the array.
  Source=OopFactory.X12.Validation
  StackTrace:
       at OopFactory.X12.Validation.X12AcknowledgmentService.AcknowledgeTransaction(X12StreamReader reader, String functionalCode, String versionIdentifierCode, String transaction) in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\OopFactory.X12.Validation\X12AcknowledgmentService.cs:line 77
       at OopFactory.X12.Validation.X12AcknowledgmentService.AcknowledgeTransactions(Stream x12Stream, Encoding encoding) in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\OopFactory.X12.Validation\X12AcknowledgmentService.cs:line 63
       at OopFactory.X12.Validation.X12AcknowledgmentService.AcknowledgeTransactions(Stream x12Stream) in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\OopFactory.X12.Validation\X12AcknowledgmentService.cs:line 33
       at X12Viewer.Form1.ParseFile() in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\X12Viewer\Form1.cs:line 71
       at X12Viewer.Form1.button1_Click(Object sender, EventArgs e) in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\X12Viewer\Form1.cs:line 28
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at X12Viewer.Program.Main() in c:\DevTFS\Tools\X12Parser\GEMMS-branch\trunk\src\X12Viewer\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
Here are links to the de-identified source file and one of the unbundled files.
Source - https://www.dropbox.com/s/r6rffgpfu3v0xvt/CLAIMS0228.NZ_out.837
Unbundled - https://www.dropbox.com/s/d4il7oweawg7tbq/CLAIMS0228.NZ.837_001_out.837
        private void SplitClaims()
        {
            string x12Filename = txtFile.Text;

            FileStream fsClaimFile = new FileStream(x12Filename, FileMode.Open, FileAccess.Read);
            fsClaimFile.Position = 0;
            X12Parser parser = new X12Parser(new SpecificationFinder(), true, new char[] { '\x1A' });

            string splitLoopId = "2300"; //Split on Loop 2300 so each claim is in a separate file
            string splitFilenameString = "{0}\\{1}_{2:000}{3}";
            string outputDir = Path.GetDirectoryName(x12Filename);

            FileInfo inputFile = new FileInfo(x12Filename);
            List<Interchange> list = new List<Interchange>();

            X12StreamReader reader = new X12StreamReader(fsClaimFile, Encoding.UTF8, new char[] { '\x1A' });
            X12FlatTransaction transaction = reader.ReadNextTransaction();
            while (!string.IsNullOrEmpty(transaction.Transactions.First()))
            {
                string x12 = transaction.ToString();
                var interchange = parser.ParseMultiple(x12).First();
                if (splitLoopId == "ST")
                    list.Add(interchange);
                else
                {
                    list.AddRange(parser.UnbundleByLoop(interchange, splitLoopId));
                }
                transaction = reader.ReadNextTransaction();
            }

            for (int i = 0; i < list.Count; i++)
            {
                string outputFilename = String.Format(splitFilenameString, outputDir, inputFile.Name, i + 1, inputFile.Extension);
                using (FileStream outputFilestream = new FileStream(outputFilename, FileMode.Create, FileAccess.Write))
                {
                    using (StreamWriter writer = new StreamWriter(outputFilestream))
                    {
                        writer.Write(list[i].SerializeToX12(false));
                        writer.Close();
                    }
                    outputFilestream.Close();
                }
            }
        }
Aug 29, 2013 at 9:49 PM
I encountered the same problem. I found the issue to be the X12StreamReader.ReadNextTransaction. My fix was to append the SE once the loop is complete:
public X12FlatTransaction ReadNextTransaction()
        {
            StringBuilder segments = new StringBuilder();

            string segmentString = ReadNextSegment();
            string segmentId = ReadSegmentId(segmentString);
            do
            {
                switch (segmentId)
                {
                    case "ISA":
                        _isaSegment = segmentString + _delimiters.SegmentTerminator;
                        break;
                    case "GS":
                        _gsSegment = segmentString + _delimiters.SegmentTerminator;
                        break;
                    case "IEA":
                    case "GE":
                        break;
                    default:
                        if (segmentId == "ST")
                            _transactionCode = SplitSegment(segmentString)[1];
                        segments.Append(segmentString);
                        segments.Append(_delimiters.SegmentTerminator);
                        break;
                }
                segmentString = ReadNextSegment();
                segmentId = ReadSegmentId(segmentString);
            } while (!string.IsNullOrEmpty(segmentString) && segmentId != "SE"); // transaction trailer segment

           if (segmentId == "SE")
            {
                segments.Append(segmentString);
                segments.Append(_delimiters.SegmentTerminator);
            }

            return new X12FlatTransaction(
                CurrentIsaSegment,
                CurrentGsSegment,
                segments.ToString());
        }