Solved

How to do something in VB script if the number of lines in the text file exceeds a value

Posted on 2016-09-07
14
28 Views
Last Modified: 2016-09-09
Hi

I have a script that already opens a file then reads lines in a text file and then does some text manipulation

Now i want it to only do this if the number of lines in the text file is greater than 37.

Sample code below

Const LogPath = "X:\Logs\"
Logfile = LogPath & "DataFix-" & FormatDateTime(Date, 1) & ".Log"

LogEvent ( "***************************************")
LogEvent ( "***************Started****************")
LogEvent ( "***************************************")

DataFix "X:\VBIN\", "X:\VOUT"

LogEvent ( "***************************************")
LogEvent ( "***************Finished****************")
LogEvent ( "***************************************")




Sub DataFix(sourceFolder,targetDir)

On Error Resume next

set objFSO = CreateObject("Scripting.FileSystemObject")   
set objDir = objFSO.GetFolder(sourceFolder)
  

for each a in objDir.Files
	
		LogEvent ("Opening " & a)

		numlines = 1
		gotHeader = False
		HeaderText_FirstLine = ""
		HeaderText_SecondLine = ""
		HeaderText_ThirdLine = ""
		IsThisBTEST = False
		IsException = False

		set objTextFile = objFSO.OpenTextFile(a)
		
		filename = objFSO.GetFileName(a)

		new1 = targetDir + "\" + left(filename, len(filename) - 4) + "_New" + right(filename, 4)	
		set w1 = objFSO.CreateTextFile(new1, True)

		
		do until objTextFile.AtEndOfStream
			strLine = objTextFile.ReadLine		


'If number of lines is greater than 37 then do below
			
	Select case left(strLine, 7)
Case "-  ACM0"	
strline = Replace (strLine, "1", "2", 1,1)
End select

			select case left(strLine, 7)					
				case "-  ACM0"
					IsThisBTEST = True
					LogEvent ("This is a valid file, continuing...")
					HeaderText_FirstLine = strLine
					If Right(strLine, 5) = "1000E" Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 13) 
						w1.WriteLine "1000E"
						IsException = True
						numlines = numlines + 1	
					Else
						
						If Right(strLine, 5) = "AAAAU" OR Right(strLine, 5) = "AAAB6" Then
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
							w1.WriteLine "1000E"
							IsException = True
							numlines = numlines + 1
						Else
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
						End If
					End If
				case else
					if IsThisBTEST = True then
						w1.WriteLine strLine
					end if
			end select

			if IsThisBTEST = True then

				if numlines = 2 and Len(HeaderText_FirstLine) > 0 then
					if IsException = False Then
						HeaderText_SecondLine = strLine
					else
						HeaderText_SecondLine = "1000E"	
					end If					
				end if

				if numlines = 3 and Len(HeaderText_FirstLine) > 0 and Len(HeaderText_SecondLine) > 0 then
					HeaderText_ThirdLine = strLine
					gotHeader = True
				end if

				if gotHeader = True and numlines = 31 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                        
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if

				if gotHeader = True and numlines = 33 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                         
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if
				
				numlines = numlines + 1
				
			end if

		loop

		w1.Close		

		if IsThisBTEST = False then
			LogEvent ("Not a valid  file - No modifications made to file.")
			objFSO.DeleteFile (new1)
		else
			LogEvent ("Completed file manipulation successfully. New file written to " & new1) 
		end if

		LogEvent ("")

		LogEvent ("Deleting original file...")
		objTextFile.Close
		objFSO.DeleteFile (a)

		LogEvent ("")

next

set objFSO = nothing

IF err.number <> 0 THEN
  LogEvent ("Error # " & CStr(Err.Number) & " " & Err.Description)
END IF

	
End Sub

'**********************************************************************
'* @name     LogEvent([])
'* @param
'* @purpose
'* @return
'*************************************************************************
sub LogEvent (sEvent)

  Dim fso
  Dim Log

  set fso = wscript.createobject("scripting.filesystemobject")
  Set Log = fso.OpenTextFile(LogFile, 8, True)
  log.writeline Time & chr(9) & sEvent
  'WScript.Echo(sEvent)
  log.close
  set fso = nothing
End Sub

Open in new window

0
Comment
Question by:wilko1000
  • 8
  • 6
14 Comments
 
LVL 25

Expert Comment

by:SStory
Comment Utility
Well, I suppose you could add a counter to count the lines and only operate on it after it reaches 37.  Or if you don't want to execute your script unless >37, you might consider some GNU tools:
http://gnuwin32.sourceforge.net/packages/coreutils.htm

The good old unix/linux tool wc does exactly this and with these tools is available on Windows
wc.exe -l yourtextfile.txt
will return the number of lines in the text file

Natively, you could do this in a batch file
type yourtextfile.txt | find /V /C ""
0
 

Author Comment

by:wilko1000
Comment Utility
Its got to be done within the script. I understand a would need a counter to count the rows within the file but Im struggling with the syntax
0
 
LVL 25

Expert Comment

by:SStory
Comment Utility
If you stick with vbscript, looking at your code, the numlines=numlines+1 will only execute inside the portion that you only want to execute if lines > 37.  
For it to work numlines=numlines +1 must always happen. I'd put it right before the next.
Then surround the block you want to control with

if numlines> 37 then
     conditional code here
end if
0
 
LVL 25

Expert Comment

by:SStory
Comment Utility
Since you are doing things with numlines, I decided to make a new variable to count total number of lines in the file.  TotalLinesInFile to count all lines regardless. The rest of your code that usings numlines won't count numlines unless TotalLinesInFile>37 So you may need to rework that to do whatever you want it to. However, it appears you want to read the header in that code. If so how will it ever do that if you don't want that code executing until 38 lines are read?

Const LogPath = "X:\Logs\"
Logfile = LogPath & "DataFix-" & FormatDateTime(Date, 1) & ".Log"

LogEvent ( "***************************************")
LogEvent ( "***************Started****************")
LogEvent ( "***************************************")

DataFix "X:\VBIN\", "X:\VOUT"

LogEvent ( "***************************************")
LogEvent ( "***************Finished****************")
LogEvent ( "***************************************")




Sub DataFix(sourceFolder,targetDir)

On Error Resume next

set objFSO = CreateObject("Scripting.FileSystemObject")   
set objDir = objFSO.GetFolder(sourceFolder)
  
for each a in objDir.Files
	
		LogEvent ("Opening " & a)

		numlines = 1
		gotHeader = False
		HeaderText_FirstLine = ""
		HeaderText_SecondLine = ""
		HeaderText_ThirdLine = ""
		IsThisBTEST = False
		IsException = False

		set objTextFile = objFSO.OpenTextFile(a)
		
		filename = objFSO.GetFileName(a)

		new1 = targetDir + "\" + left(filename, len(filename) - 4) + "_New" + right(filename, 4)	
		set w1 = objFSO.CreateTextFile(new1, True)

		
                TotalLinesInFile=0
		do until objTextFile.AtEndOfStream
			strLine = objTextFile.ReadLine		


'If number of lines is greater than 37 then do below\
if TotalLinesInFile>37 then
			
	Select case left(strLine, 7)
Case "-  ACM0"	
strline = Replace (strLine, "1", "2", 1,1)
End select

			select case left(strLine, 7)					
				case "-  ACM0"
					IsThisBTEST = True
					LogEvent ("This is a valid file, continuing...")
					HeaderText_FirstLine = strLine
					If Right(strLine, 5) = "1000E" Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 13) 
						w1.WriteLine "1000E"
						IsException = True
						numlines = numlines + 1	
					Else
						
						If Right(strLine, 5) = "AAAAU" OR Right(strLine, 5) = "AAAB6" Then
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
							w1.WriteLine "1000E"
							IsException = True
							numlines = numlines + 1
						Else
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
						End If
					End If
				case else
					if IsThisBTEST = True then
						w1.WriteLine strLine
					end if
			end select

			if IsThisBTEST = True then

				if numlines = 2 and Len(HeaderText_FirstLine) > 0 then
					if IsException = False Then
						HeaderText_SecondLine = strLine
					else
						HeaderText_SecondLine = "1000E"	
					end If					
				end if

				if numlines = 3 and Len(HeaderText_FirstLine) > 0 and Len(HeaderText_SecondLine) > 0 then
					HeaderText_ThirdLine = strLine
					gotHeader = True
				end if

				if gotHeader = True and numlines = 31 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                        
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if

				if gotHeader = True and numlines = 33 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                         
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if
				
				numlines = numlines + 1
				
			end if

		loop

		w1.Close		

		if IsThisBTEST = False then
			LogEvent ("Not a valid  file - No modifications made to file.")
			objFSO.DeleteFile (new1)
		else
			LogEvent ("Completed file manipulation successfully. New file written to " & new1) 
		end if

		LogEvent ("")

		LogEvent ("Deleting original file...")
		objTextFile.Close
		objFSO.DeleteFile (a)

		LogEvent ("")
   end if
   
   TotalLinesInFile=TotalLinesInFile+1
next

set objFSO = nothing

IF err.number <> 0 THEN
  LogEvent ("Error # " & CStr(Err.Number) & " " & Err.Description)
END IF

	
End Sub

'**********************************************************************
'* @name     LogEvent([])
'* @param
'* @purpose
'* @return
'*************************************************************************
sub LogEvent (sEvent)

  Dim fso
  Dim Log

  set fso = wscript.createobject("scripting.filesystemobject")
  Set Log = fso.OpenTextFile(LogFile, 8, True)
  log.writeline Time & chr(9) & sEvent
  'WScript.Echo(sEvent)
  log.close
  set fso = nothing
End Sub

Open in new window

0
 

Author Comment

by:wilko1000
Comment Utility
Its an old script that i hoped to use without having to create another.
I get Loop without do  error on line 121 when i run that up
0
 
LVL 25

Expert Comment

by:SStory
Comment Utility
I just copied your script and added the counter and the if condition.  I'm not sure what you wanted conditions around. I also don't think it will work as you may wish, but your questions is how to make it only run a certain part of code if lines read >37. That is what I am answering. Does this execute? If so you have the >37 condition solved, but need to rethink the logic on the rest.  Or you need to spell out what you really want it to do.
Const LogPath = "X:\Logs\"
Logfile = LogPath & "DataFix-" & FormatDateTime(Date, 1) & ".Log"

LogEvent ( "***************************************")
LogEvent ( "***************Started****************")
LogEvent ( "***************************************")

DataFix "X:\VBIN\", "X:\VOUT"

LogEvent ( "***************************************")
LogEvent ( "***************Finished****************")
LogEvent ( "***************************************")




Sub DataFix(sourceFolder,targetDir)

On Error Resume next

set objFSO = CreateObject("Scripting.FileSystemObject")   
set objDir = objFSO.GetFolder(sourceFolder)
  
for each a in objDir.Files
	
   LogEvent ("Opening " & a)

	numlines = 1
	gotHeader = False
	HeaderText_FirstLine = ""
	HeaderText_SecondLine = ""
	HeaderText_ThirdLine = ""
	IsThisBTEST = False
	IsException = False

	set objTextFile = objFSO.OpenTextFile(a)
	
	filename = objFSO.GetFileName(a)

	new1 = targetDir + "\" + left(filename, len(filename) - 4) + "_New" + right(filename, 4)	
	set w1 = objFSO.CreateTextFile(new1, True)

	
   TotalLinesInFile=0
	do until objTextFile.AtEndOfStream
	   strLine = objTextFile.ReadLine		


      'If number of lines is greater than 37 then do below\
      if TotalLinesInFile>37 then
      	Select case left(strLine, 7)
            Case "-  ACM0"	
               strline = Replace (strLine, "1", "2", 1,1)
         End select

			select case left(strLine, 7)
				case "-  ACM0"
					IsThisBTEST = True
					LogEvent ("This is a valid file, continuing...")
					HeaderText_FirstLine = strLine
					If Right(strLine, 5) = "1000E" Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 13) 
						w1.WriteLine "1000E"
						IsException = True
						numlines = numlines + 1	
					Else
						
						If Right(strLine, 5) = "AAAAU" OR Right(strLine, 5) = "AAAB6" Then
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
							w1.WriteLine "1000E"
							IsException = True
							numlines = numlines + 1
						Else
							w1.WriteLine Left(HeaderText_FirstLine, 8) & "1014" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
						End If
					End If
			   case else
					if IsThisBTEST = True then
						w1.WriteLine strLine
					end if
			end select

			if IsThisBTEST = True then

				if numlines = 2 and Len(HeaderText_FirstLine) > 0 then
					if IsException = False Then
						HeaderText_SecondLine = strLine
					else
						HeaderText_SecondLine = "1000E"	
					end If					
				end if

				if numlines = 3 and Len(HeaderText_FirstLine) > 0 and Len(HeaderText_SecondLine) > 0 then
					HeaderText_ThirdLine = strLine
					gotHeader = True
				end if

				if gotHeader = True and numlines = 31 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                        
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1003" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if

				if gotHeader = True and numlines = 33 then
					if IsException = False Then
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Right(HeaderText_FirstLine, Len(HeaderText_FirstLine) - 8)
					else
                                         
						w1.WriteLine Left(HeaderText_FirstLine, 8) & "1004" & Mid(HeaderText_FirstLine, 9, Len(HeaderText_FirstLine) - 16)&"FED"
					end if
					
				end if
				
				numlines = numlines + 1
				
			end if 'if IsThisBTEST
      end if 'if >37
	loop

	w1.Close		

	if IsThisBTEST = False then
		LogEvent ("Not a valid  file - No modifications made to file.")
		objFSO.DeleteFile (new1)
	else
		LogEvent ("Completed file manipulation successfully. New file written to " & new1) 
	end if

	LogEvent ("")

	LogEvent ("Deleting original file...")
	objTextFile.Close
	objFSO.DeleteFile (a)

	LogEvent ("")
   
   TotalLinesInFile=TotalLinesInFile+1
next

set objFSO = nothing

IF err.number <> 0 THEN
  LogEvent ("Error # " & CStr(Err.Number) & " " & Err.Description)
END IF

	
End Sub

'**********************************************************************
'* @name     LogEvent([])
'* @param
'* @purpose
'* @return
'*************************************************************************
sub LogEvent (sEvent)

  Dim fso
  Dim Log

  set fso = wscript.createobject("scripting.filesystemobject")
  Set Log = fso.OpenTextFile(LogFile, 8, True)
  log.writeline Time & chr(9) & sEvent
  'WScript.Echo(sEvent)
  log.close
  set fso = nothing
End Sub

Open in new window


Can you write in a paragraph what you hope to accomplish with this script?  I wonder if something like the grep command and possibly sed, couldn't be used to accomplish it.  They are part of the gnu32 mentioned above.
0
 

Author Comment

by:wilko1000
Comment Utility
Script is doing nothing now it just loops around then exits if when the number of lines in the file being read is 38.

Sorry if its not clear so will try and explain better.

I have a script that opens a file, reads it line by line and maniplates the text within it (in summary if first line has "-  ACM0" then it copys the first line to lines 31 and 33 and then adds a bit of text).
That works fine.

Now i would like the script to exit if the number of lines with the text file is less than 37. If the number of lines is greater than or equal to 37 then proceed with the manuipluation  at line 46:

Select case left(strLine, 7)
            Case "-  ACM0"      etc etc....
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 25

Expert Comment

by:SStory
Comment Utility
I knew it would do nothing. You question was how to make it stop and only do a section if 37 lines had been read. "Now i want it to only do this if the number of lines in the text file is greater than 37."

So my changes count the number of lines read and if >37 allow your code to run. Since your code tries to work with line 1 I don't see how it would ever work. It would sure be nice to see a sample file and same desired outcome as there may be an easier way.  Also I don't know how you can manipulate the first line and not do anything until there are 38 lines at the same time.  The only thing I can think of, is open the file, loop through to read the total number of lines, close the file, reopen and if >37 process it normally.  There are text based commands like grep, awk and sed that are made for Linux/Unix, but available to Windows through http://gnuwin32.sourceforge.net/packages/coreutils.htm that might allow you to do this without all the code. It depends upon what you are trying to accomplish.

if there is a way to show a sample input file (fake data fine) and desired result, it might be helpful.

I assume by "copys the first line to lines 32 and 33, you mean it copies to the variables on lines 31-33 in the script:
HeaderText_FirstLine = ""
HeaderText_SecondLine = ""
HeaderText_ThirdLine = ""

And not lines 31-33 of the output.

There is no other way to process the first part and then know there are 38 lines.  If I understand you want to throw out log files < 38 lines?  Or do you want to stop processing if <38 lines. The next question is when you run out of lines <38 processing is going to quit anyway so I still am not sure what you want to do.
0
 

Author Comment

by:wilko1000
Comment Utility
Thank you for your input and again appolgies if im not clear.

I have attached a sample file for reference. The file has 39 lines. The script would need to open the file, count how many lines are in it and if > 38 then proceed if not then close the script. Not bothered about logging at this stage.

I had a go at counting the lines before it created the file and modifes the content as follows with a little success:

I modifed and added these lines and managed to count the lines
FROM
set objTextFile = objFSO.OpenTextFile(a)
TO
set objTextFile = objFSO.OpenTextFile(a, ForReading)

AND ADDED THIS
ForReading = 1

Do While objTextFile.AtEndOfStream <> True
    objTextFile.SkipLine
Loop

and if i write this out it shows me the total lines in the file before it creates the file

wscript.echo objTextFile.Line-1

But if i can get it to carry on if the number of lines >38 that would be great

I added this but fails:

If objTextFile > 38 then
 create the  file....etc etc (line 40)
Test-File.txt
0
 
LVL 25

Expert Comment

by:SStory
Comment Utility
OK. You open a file like the attached. Then you do what?  Do you look at line one for ACM01 or do you count down 37 lines and do something?  If you count down 38 lines, how do you get line 1?  There is still no clear methodology as to what you want to do.  Do we count the lines in the file to determine if long enough to process before beginning? Or do we process from the start until we find out that there aren't enough lines (>37) and then quit? Or what?

I don't know what you mean exactly still but I imagine:

Do While objTextFile.AtEndOfStream <> True
    objTextFile.SkipLine
Loop

NumLines=objTextFile.Line-1

'close the file
objTextFile.Close

if (NumLines) > 37 then
   'reopen the file and process it with whatever code you want--knowing that there are more than 37 lines
   
end if

Open in new window

0
 

Author Comment

by:wilko1000
Comment Utility
Hi

yes  count the lines in the file to determine if long enough to process as the first step before beginning. if the number of lines in the file are short (i.e. count if number of lines is 37 or less) exit the proram and not do anything

The file i attached has 39 lines so first step would be to validate to see if the number of lines in file greater than 37 and if so contiune to manipulate the file (check for - AMC0 etc). But if the file had less than 37 lines or less dont do anything, stop the process.
0
 
LVL 25

Accepted Solution

by:
SStory earned 500 total points
Comment Utility
OK. The code sample I gave you above your post does that. You just need to put your original processing code inside the second if body to do what you want it to because that is where it is definitely >37 lines.
0
 

Author Closing Comment

by:wilko1000
Comment Utility
That does what i want. Thank you for your patience, really helped thanks
0
 
LVL 25

Expert Comment

by:SStory
Comment Utility
You are welcome!
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

This is an addendum to the following article: Acitve Directory based Outlook Signature (http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_24950055.html) The script is fine, and works in normal client-server domains…
Welcome, welcome!  If you are new to the series and haven't been following along, please take a brief moment to review the first three installments: Part 1 (http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/A_266-VBScri…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now