Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Pulling Data from a Huge Cursor
Message
From
03/03/2014 05:41:25
 
 
To
02/03/2014 13:01:13
Mike Yearwood
Toronto, Ontario, Canada
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Environment versions
Visual FoxPro:
VFP 9 SP2
OS:
Windows Server 2012
Network:
Windows 2008 Server
Database:
MS SQL Server
Application:
Web
Miscellaneous
Thread ID:
01595090
Message ID:
01595650
Views:
80
Thank you So much sir. What I am trying is to extract Pages from a huge File. My file is actually is a Huge PS (or you can say a txt file). Which contains multiple bills. Some of 1 Page some of 2 some of 3 etc. Please use Notepad to open this file.

At step 1 I am taking out the Header Part (Common Part that should be in all Files) to a separate cursor called Cursor_hearder and than extracting Each Bill in a Separate File.


I need to Split this file Bill Wise. So I am taking the Entire file in a cursor First and than trying to split it. Using the code below, I am able to split it, but the process is very slow and therefore , if the number of bills are large the time will be huge and my ultimate purpose will not be solved.

If you give me a bit different code that will make the performance better will be really very helpful. I will accordingly make the changes in rest of codes also.

Here Is the original File
https://www.dropbox.com/s/c8kelwnelpmiu1w/M01_08082013_CTK_08062013_753012.ps.gz

Here is sample Splited file as generated by my code
https://www.dropbox.com/s/mfc0n0u8ovsx832/Sampleps.rar


Here is my relevant code
Set Optimize On
Select New_Bills
Scan  && Scans for New_bills up to EOF()
	cPsfilepath=Alltrim(Fullpath)
	Newpath=Alltrim(Newpath)
	Create Cursor Cursor_AllBills (POS varchar(254),PAGENUM I,posR N(8,3),posC N(8,3)) && Create Temporary Cursor For Cursor_AllBills
	Select Cursor_AllBills
	Append From (m.cPsfilepath) Sdf
	Locate For Alltrim(POS)='%%EndSetup:'
	HeaderRecordNumber=Recno() && Finds the Header Record Number for Each PS File
	SELECT POS FROM Cursor_AllBills INTO CURSOR Cursor_Header Where Recno()<= HeaderRecordNumber 
	Delete From Cursor_AllBills Where Recno()<= HeaderRecordNumber
	Do Split
ENDSCAN

PROCEDURE Split

Select New_Bills

Scan  && Scans for New_bills up to EOF()
	cPsfilepath=Alltrim(Fullpath)
	Newpath=Alltrim(Newpath)
	Create Cursor Cursor_AllBills (POS varchar(254),PAGENUM I,posR N(8,3),posC N(8,3)) && Create Temporary Cursor For Cursor_AllBills
	Select Cursor_AllBills
	Append From (m.cPsfilepath) Sdf
	Locate For Alltrim(POS)='%%EndSetup:'
	HeaderRecordNumber=Recno() && Finds the Header Record Number for Each PS File
	SELECT POS FROM Cursor_AllBills INTO CURSOR Cursor_Header Where Recno()<= HeaderRecordNumber 
	Delete From Cursor_AllBills Where Recno()<= HeaderRecordNumber
	Do Split
Endscan

*Now We will Split and Compress it
Procedure Split
Select Cursor_AllBills
Select Count(POS) From Cursor_AllBills Where Left(Alltrim(POS),9)='%%Page: 1' ;
Into Array nNumberofbillsincurrentfile && Counts The Number of Bills in Current File
nBillend=0 && Start Position for Searching Location of  %%Page: 1

For I=1 To m.nNumberofbillsincurrentfile && Loop to Separate Each Bill and Compress it.
	Select Cursor_AllBills
	Locate For Left(Alltrim(POS),9)='%%Page: 1' And Recno()>m.nBillend
	nPageonestart=Recno()
	Locate For Left(Alltrim(POS),9)='%%Page: 2' And Recno()>m.nPageonestart
	nPageoneend=Recno()
	Locate For Left(Alltrim(POS),9)='%%Page: 1' And Recno()>m.nPageoneend
	nBillend=Recno()
Select * From Cursor_AllBills Into Cursor Cursor_Splitedfile Where Recno()=>m.nPageoneend And Recno()<m.nBillend Readwrite
Locate For Strextract(POS,'(',')')='Account Number'
Skip
oFileName=Strextract(POS,'(',')')
oFileName='C:\HARSH\'+oFileName+'.Ps'

*** Here the Size of POS exceeds 255 hence we will delete some ... to make it below 255 CHaracter
Locate For Right(Alltrim(POS),9)='. . . .)S'
IF Found()
Replace POS With Left(Alltrim(POS),250)+'.)SH'
Endif


Select Count(POS) From Cursor_Splitedfile Where Left(Alltrim(POS),7)='%%Page:' Into Array lnPagecount
Select Cursor_Splitedfile
nAssignpagenumberRecno=0

For nAssignpagenumber=1 To m.lnPagecount
Locate For Left(Alltrim(POS),7)='%%Page:' And Recno()>m.nAssignpagenumberRecno
If Found()
nAssignpagenumberRecno=Recno()
Replace POS With '%%Page: '+Alltrim(Str(m.nAssignpagenumber))+' '+Alltrim(Str(m.lnPagecount))
Endif
Endfor

Set Textmerge On
Set Textmerge To (m.oFileName) Noshow
Scan
\\<< TRIM(POS) >>
\
Endscan
Set Textmerge To
Set Textmerge Off

WAIT WINDOW I Nowait
Endfor

Return
Endproc
>Hi Harsh
>
>I have no problem helping you. You are attempting to do the work and are asking for better ways to do it. You do not seem to be saying "here is my problem, write me the code for free".
>
>I know if someone is asking for help it is because they don't yet know how to do it better and want to learn. They may also know a lot, but seek a better idea.
>
>You are trying to process a page at a time. I really want you to provide a few sample pages and a few sample sets of records so I can write code using that. Then I can post code for you to try. You can learn from the code and others can provide more input.
>
>>Hi,
>>Kindly Consider the following code. The Code Is Extracting Data Between Two '%%Page: 1' From a Cursor.
>>
>>There are over 1800000 Records and I need to Extract Data From Start of '%%Page: 1' to One Prior Record Before next '%%Page: 1'. Than again From Next '%%Page: 1' to One Prior Record Before next '%%Page: 1'.
>>
>>But Gradually The Extraction becomes Slow and becomes very consuming.
>>
>>Is there can be any SQL for such Purpose that May serve better
>>
>>Note:- Please Do Not suggest Indexing as I will not serve my purpose, perhaps.
>
>I think you need to know more about how FoxPro thinks so you might be better not putting limits on the answers.
>
>I absolutely insist you have an index on left(alltrim(pos),9). VFP will use that index to find the page records very fast. Since you are processing so many records, you need all the speed you can get.
>
>Every time a LOCATE FOR executes it takes a chunk of time. Generally speaking, if you have the correct indexes it will take less time.
>
>FoxPro has SQL in it, but RECNO() is not a SQL concept. It is not optimizable and will not be fast for SQL. Better to use FoxPro commands instead.
>
>>
>>
>>SELECT ALLBILLS
>>SELECT COUNT(POS) FROM Allbills WHERE LEFT(ALLTRIM(pos),9)='%%Page: 1' INTO ARRAY nNumberofbillsincurrentfile
>>nBillend=0
>>FOR I=1 TO m. nNumberofbillsincurrentfile
>>SELECT AllBILLS
>>LOCATE FOR LEFT(ALLTRIM(POS),9)='%%Page: 1' AND RECNO()>m.nBillEnd && Bill Starts From Here and This is the First Page
>>nPageonestart=RECNO()
>>LOCATE REST FOR LEFT(ALLTRIM(POS),9)='%%Page: 2' AND RECNO()>m.nPageonestart && Page One Ends Here
>>nPageoneend=RECNO()
>>LOCATE REST FOR LEFT(ALLTRIM(POS),9)='%%Page: 1' AND RECNO()>m.nPageoneend && Next Bills Starts From Here
>>nBillEnd=RECNO()
>
>GO m.nPageOneEnd
>lcFileName = STREXTRACT(POS,'(',')')
>
>>LOCATE REST FOR STREXTRACT(POS,'(',')')='Account Number' AND RECNO()>m.nPageoneend AND RECNO()<m.nBillend
>>SKIP
>
>
>Don't use oFilename. o is usually used for an object variable type. This will be very confusing. It should be cFileName
>>cFileName=STREXTRACT(POS,'(',')')
>>cFileName='D:\HARSH\'+oFileName+'.Ps'
>
>Are you near the record you want below after the SKIP above? LOCATE FOR cannot optimize the following without an index. But if the next few records after the above contains the string you seek, you could do LOCATE REST FOR and it will get there really fast.
>
>>LOCATE REST FOR ALLTRIM(POS)="20.699 184.238 MV (. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .)S"
>>Replace POS WITH '20.699 184.238 MV (. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . )SH'
>
>If the above is really what you mean to do, it seems the only difference is adding an H to the end of POS. Here's how:
>REPLACE POS WITH ALLTRIM(POS) + "H"
>
>
>SELECT cannot use RECNO() to optimize. DO NOT ADD AN INDEX ON RECNO()!!! Very dangerous.
>>SELECT POS FROM Allbills INTO CURSOR Splitfile Where RECNO()=>m.nPageoneend AND RECNO()<m.nBillEnd Readwrite
>
>I think you might try..
>GO m.nPageoneend 
>COPY REST TO splitfile.DBF WHILE RECNO()<m.nBillEnd
>USE splitfile in select("splitfile")
>SELECT splitfile
>
>>Set Textmerge ON
>>Set Textmerge To (m.cFileName) Noshow
>>SCAN
>>\\<< TRIM(POS) >>
>>\
>>ENDSCAN
>>Set Textmerge To
>>Set Textmerge OFF
>
>
>
>*DO NOT EVER USE RECNO() with SQL commands.
>>DELETE FROM Allbills Where RECNO()=>m.nPageonestart AND RECNO()<=m.nBillEnd
>
>Do this instead.
>
>SELECT ALLBILLS
>GO m.nPageOneStart
>DELETE REST WHILE RECNO()<=m.nBillEnd
>
>
>>WAIT WINDOW I Nowait
>>ENDFOR
>>
Harsh
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform