Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Parsing a file that's not quite comma-delimited
Message
From
10/07/2007 12:50:51
 
 
To
10/07/2007 11:12:04
Jay Johengen
Altamahaw-Ossipee, North Carolina, United States
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Environment versions
Visual FoxPro:
VFP 8 SP1
Miscellaneous
Thread ID:
01238841
Message ID:
01238977
Views:
18
>>Very similar to EDI. Is there always a CR, LF, or some sort of character at the end of each record (which is called a segment in EDI terms)?
>
>I haven't seen the output specs in detail, but it looks like there is. Peter posted some code that looks like a good start. Did you have any other ideas?

Okay, this code requires uses Vlad's collection class: Download #9858 < update > Hmmm...apparently I've made some sort of change to his class. Maybe it will work as is.

The edisegment class below probably could use some improvement, but it works. This is just an example showing how it parses.
text to lcInput noshow textmerge
MSH|^~\&|Medinotes|CP|External||20070705154008||DFT^P03|468D4AD320F3|P|2.4|||AL|||
EVN|P03|20070705154008|20070705154008
PID|1|11384|468AE48A7926||Johengen^Jay||20051108000000||||||||||||
PV1|1|O|Ambulatory Surgery Center^^^^^^^^Ambulatory Surgery Center||||^Cardio^Full||||20070705154008||
ORC|SN|
FT1|1|||20070705154008||CG||||||||||^^^Ambulatory Surgery Center|||250.00^Diabetes Mellitus snip^C4|
DG1|1||250.00^Diabetes Mellitus Without Mention Of Complication, Type II snip^I9|||F

endtext

* like Peter said, you can use filetostr() to create lcinput

dimension laLines[1]
lnLines = alines(laLines, lcInput)

for i = 1 to lnLines

	oSeg = newobject("edisegment","","",laLines[i],"|")  && pass in segment and segment separator
	
	? oSeg.elements[1]
	
	do case 
		case oSeg.elements[1] = "MSH"
			? "We've got some notes here!"
		case oSeg.elements[1] = "EVN"
			? "Do something with EVN"
		case oSeg.elements[1] = "PID"	
			? oSeg.elements[6]   && Hey Jay!  :)
		otherwise
			* do something else
	endcase
next i


* simple class for parsing and creating EDI segments
DEFINE CLASS ediSegment AS custom

	Name = "ediSegment"
	DIMENSION elements[1]
	segmentName = ''
	segSep = chr(21)
	elementSep = chr(42)
	lTrimMode = .t.			&& determines whether new elements are trimmed when
							&& added to the segment
	cSegment = ''
	elementCount = 0

	procedure init
	lparameters lcSegment, lcElementSep


		local oTemp
	
		oTemp = newObject('ColManager','coll.vcx')
		this.AddProperty('CollectionManager',oTemp)
		dodefault()

		if len(lcSegment) <= 3   	&& creating new segment
			this.segmentName = lcSegment
			if len(lcElementSep) = 1
				this.elementSep = lcElementSep
			endif
		else						&& parse existing segment
			if vartype(lcElementSep) = 'C' and len(lcElementSep) = 1
				this.cSegment = lcSegment
				this.elementSep = lcElementSep					
				this.elementCount = this.parse(lcSegment)
			else
				error "Invalid element separator passed into "+chr(13)+chr(10)+;
						"ediSegment.init() method"
			endif
		endif
	endproc
	
	procedure new
	lparameters lcSegmentName
		this.segmentName = lcSegmentName
		
		this.CollectionManager.clear()
	endproc
	

	*******************************************************************************
	function setTrimOff() && setTrimOn()
	*
	*      Purpose: Turn trim mode for segment off or on.  When trim mode is on,
	*					new elements are trimmed before they are added to segment
	*
	*-----------------------------------------------------------------------------*
		this.lTrimMode = .f.
	endproc
	function setTrimOn
		this.lTrimMode = .t.
	endproc
	*-----------------------------------------------------------------------------*

	*******************************************************************************
	function parse
	*
	*      Purpose: Parse an EDI segment into elements (fields)
	*
	*   Parameters: lcSegment
	*					String containing segment.  Must contain element
	*					separators, and last character MUST be a segment separator
	*					or an element separator.

	*-----------------------------------------------------------------------------*
	lparameters lcSegment
		local lcBuf, lnSize, nElements

		nElements = 0
		
		lcBuf = lcSegment
		lcBuf = alltrim(lcSegment)
		lcBuf = stuff(lcBuf, len(lcBuf), 1, this.elementSep)

		lnSize = at(this.elementSep, lcBuf) - 1

		do while lnSize >= 0   && empty elements are totally legal!!!

			if nElements = 0
				this.segmentName = substr(lcBuf, 1, lnSize)

			endif

			this.elements.add(substr(lcBuf, 1, lnSize))
			

			lcBuf = substr(lcBuf, lnSize + 2)
			nElements = nElements + 1
			lnSize = at(this.elementSep, lcBuf) - 1
		enddo

	    return nElements
	endproc &&-- parse
	*-----------------------------------------------------------------------------*
	

	function getSegmentString
		local lcSegment, i
		lcSegment = this.segmentName

		i = 1
		for each element in this.elements.items
			lcSegment = lcSegment + this.elementSep + element
			i = i + 1
		next element
		lcSegment = lcSegment + this.segSep
		return lcSegment
	endproc	
	
	procedure elements_access
		lparameters puIndex
		if vartype(puIndex) == 'L' && access as object
			return this.collectionManager
		else
			if puIndex <= this.elementCount
				return this.collectionManager.Items[m.puIndex]
			else
				return .f.
			endif
		endif
	endproc

	procedure elements_assign
		lParameters leNewVal, puindex
		lcNewVal = transform(leNewVal)
		if this.lTrimMode
			lcNewVal = alltrim(lcNewVal)
		endif
		this.collectionManager.setitems(puindex, lcNewVal)
	endproc

	procedure Destroy
		dodefault()
		this.CollectionManager = ''
	endproc

enddefine
Steve Gibson
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform