2016-09-29 83 views
1

我编写了一个自定义函数来解析HL7接口消息。这些是在医疗信息系统之间发送的消息,但基本上它只是一个长字符串,用各种字符分隔以指示不同的字段,我将它们粘贴到Excel中的单元格中。我创建的函数搜索并计数以查找参数中指定的字段。在自定义HL7分析函数中为可选参数添加逻辑

免责声明:我是VBA新手。在过去的3-4周里,我一直在通过在线调查和反复试验来教导自己,所以我不是VBA专家。我宁愿不使用数组,因为当我尝试时,代码对我来说太复杂了,无法排除故障。所以,我相信代码很容易遵循,而不是最快/最有效的。

无论如何,我已经很好地做了我想做的事情,但我坚持要在逻辑中添加OPTIONAL参数。

所以,这就是我想要的工作:

=KWHL7(A1, "MSH", 8)

注意只有3个参数

结果我想ADT^A08

结果我得到ADT

注意我知道我告诉它停止在“HL7_SUBFIELD_DELIMITER”的下一个实例“^”

=KWHL7(A1, "MSH", 8,1)

注意可选的第四个参数

结果我想ADT

=KWHL7(A1, "MSH", 8,2)

注意可选的第四个参数

结果我想A08

内容的单元格A1的 “价值”:

<11>MSH|^~\&|OPS|384|RISIC|384|20160923093012||ADT^A08|Q1230569238T1410271390|P|2.3|||*PM_ALLERGY*|||8859/1<13> 
EVN||20160923<13> 
PID|1||000000808^^^SCH MRN^MRN^SC||ZZTEST^LEANN||20160706|F|||459 CORPORATION ST.^^BEAVER^PA^15009^USA||(724)775-7418^PRN|||S||000000008082^^^SCH Account Number^FIN NBR|||||||0<13> 
PV1|1|I|SCH Periop^^^^^^||||08888^Bullian^Leann~08888^Naylor^Daniel|||10|||||||08888^Nguyen-potter^Rose~00187^TEST^STCHRISRES^L^MD^^MD^^SCH Doc Number|1|1287593^^^TEMP FIN^VISITID||||||||||||||||||||384||A|||20160707131900<13> 
PV2|||PA^<13> 
OBX|1||Dosing Weight^WEIGHT||5|kg<13> 
OBX|2||Height^HEIGHT||25|cm<13> 
AL1|1|Drug|d00308^morphine^Multum Drug||66382015<13> 
ZAL|||16655315|16655315||Active|66382015^Anaphylaxis^673967||||20160923093008|^Naylor^Daniel|0<13> 
AL1|3|Drug|d00012^codeine^Multum Drug||103576018<13> 
ZAL|||16655323|16655307||Active|103576018^Diarrhea^673967||||20160923093008|^Naylor^Daniel|0<13> 
<28><13> 

我的VBA代码(对不起,所有的意见,我只是学习!):

Public Function KWHL7(KW_Cell_With_HL7_Message As Variant, KW_HL7_Segment_Name As String, KW_HL7_Field_Number As Integer) 

        'KW_Cell_With_HL7_Message = KW_Cell_With_HL7_Message.Value 
        'KW_Cell_With_HL7_Message = ActiveCell.Value 
        'KW_HL7_Segment_Name = "PID" 
        'KW_HL7_Field_Number = 18 

     Const HL7_SEGMENT_DELIMITER = vbLf 'using "<13>" did not work due to carriage return 
     Const HL7_FIELD_DELIMITER = "|" ' Pipe means next field 
     Const HL7_SUBFIELD_DELIMITER = "^" 
      'Various carriage returns and line breaks: vbLf, vbCr, vbCrLf, vbNewLine, Chr(10), Chr(13) 

     KWSegmentStringToSearchFor = HL7_SEGMENT_DELIMITER & KW_HL7_Segment_Name 'Using the segment delimiter ("<13>" or "vbLf"/carriage return) before segment name implies that the segment/line STARTS with this text 

     KWSegmentCharacterPosition = InStr(1, KW_Cell_With_HL7_Message, KWSegmentStringToSearchFor) 
     '** FOR TESTING ** MsgBox ("Segment Character Position: " & KWSegmentCharacterPosition & ", 5 Characters starting there = " & Mid(KW_Cell_With_HL7_Message, KWSegmentCharacterPosition, 5)) 

     'Now we have the character position of the start of the proper SEGMENT/line 
     'Now we have to find the Proper Field in that segment 
     'So we'll use this position + the length of the end of the Segment Delimiter as the start 
     '***WARNING***: Still must add logic to make sure we stop if we encounter another Segment Delimiter 

     KWFieldCharacterPosition = KWSegmentCharacterPosition + Len(HL7_SEGMENT_DELIMITER) 'instead of starting at character 0, start at the beginning of the segment found previously 
     ' ** FOR TESTING ** MsgBox ("Length of Segment Delimiter = " & Len(HL7_SEGMENT_DELIMITER)) 
     ' ** FOR TESTING ** MsgBox ("Field Character Position: " & KWFieldCharacterPosition & ", 5 Characters starting there = " & Mid(KW_Cell_With_HL7_Message, KWFieldCharacterPosition, 5)) 

     For J = 1 To KW_HL7_Field_Number 
     KWFieldCharacterPosition = InStr(KWFieldCharacterPosition + 1, KW_Cell_With_HL7_Message, HL7_FIELD_DELIMITER) 
     If KWFieldCharacterPosition = 0 Then Exit For 
     Next 

     ' ** FOR TESTING ** MsgBox ("Field Character Position: " & KWFieldCharacterPosition & ", 5 Characters starting there = " & Mid(KW_Cell_With_HL7_Message, KWFieldCharacterPosition, 5)) 

     'Determine the number of characters to return after the start position 
     'Want to pull text UNTIL the next Segment Delimiter or Field Delimiter or Subfield Delimiter 

     'Find the position of the next Segment Delimiter or Field Delimiter or Subfield Delimiter 
     'Since the InStr function does not accept multiple substrings to search for, and does not allow OR statements inside... 
     Next_HL7_Segment_Delimiter = InStr(KWFieldCharacterPosition + 1, KW_Cell_With_HL7_Message, HL7_SEGMENT_DELIMITER) 
     Next_HL7_Field_Delimiter = InStr(KWFieldCharacterPosition + 1, KW_Cell_With_HL7_Message, HL7_FIELD_DELIMITER) 
     Next_HL7_Subfield_Delimiter = InStr(KWFieldCharacterPosition + 1, KW_Cell_With_HL7_Message, HL7_SUBFIELD_DELIMITER) 

     'Added logic to handle issue where the next delimiter was not found, making result 0, making it the lowest value in the next lines of code 
     If Next_HL7_Segment_Delimiter = 0 Then Next_HL7_Segment_Delimiter = 99999 
     If Next_HL7_Field_Delimiter = 0 Then Next_HL7_Field_Delimiter = 99999 
     If Next_HL7_Subfield_Delimiter = 0 Then Next_HL7_Subfield_Delimiter = 99999 

     'Set the Last Character Position to whichever Next Delimiter is the lowest/minimum number - Segment or Field or Subfield 
     KWLastCharacterPosition = WorksheetFunction.Min(Next_HL7_Segment_Delimiter, Next_HL7_Field_Delimiter, Next_HL7_Subfield_Delimiter) 
     ' ** FOR TESTING ** MsgBox ("Last Character Position: " & KWLastCharacterPosition & ", 5 Characters starting there = " & Mid(KW_Cell_With_HL7_Message, KWLastCharacterPosition, 5)) 

     'Determine the number of characters to return in the MID function by subtracting the first character position from the last character position 
     KWNumberOfCharactersToReturn = KWLastCharacterPosition - KWFieldCharacterPosition - 1 
     ' ** FOR TESTING ** MsgBox ("Number of characters to return: " & KWNumberOfCharactersToReturn) 

     KWResult = Mid(KW_Cell_With_HL7_Message, KWFieldCharacterPosition + 1, KWNumberOfCharactersToReturn) 
        'MsgBox ("Result: Segment " & KW_HL7_Segment_Name & ":" & KW_HL7_Field_Number & " is " & KWResult) 
        KWHL7 = KWResult 
End Function 

我曾与使用问题拆分功能是将所有内容放入数组中。由于我需要在查找FIRST的KWSegmentStringToSearchFor(即“MSH”或“PV1”)之前,在查询管道(|)字符之前,我需要该数组拥有单独的嵌套数组,并且它对我来说过于混乱。

所以我放弃了拆分功能,并且我最初的计划是使用数组,并且只写了所有的东西来顺序地查找东西。因此它使用InStr()搜索KWSegmentStringToSearchFor(即“MSH”或“PV1”),然后统计管道(|)字符以确定要返回哪个数字段。

由于字符串长度可变,但用特殊字符分隔,因此接下来我必须确定要使用MID函数返回多少个字符。因此,我搜索下一个分隔符FROM THERE /使用我发现的字段作为起点,并称此字段结束。

问题: 该逻辑将3个可能的分隔符中的任何一个视为该字段的结尾。 如果我拿出来,代码将不知道字符串的末尾在哪里。

即使我添加了一些IF语句,如果可选的第四个参数存在(我不知道该怎么做),那么忽略^作为分隔符......总是会返回完整的字段(ADT^A08)。它不会仅返回我想要的子字段/组件。

谢谢!

回答

0

简单的回答,将分割上换行那么它可能需要的调整将是,split(range("a1").value,"|")(intFieldNumber)
split("11>MSH|^~\&|OPS|384|RISIC|384|20160923093012||ADT^A08|Q1230569238T1410271390","|")(8)

给出结果ADT^A08