I've had this function for almost two years now, and I can't seem to figure out why it's not working for colorizing. Here's the entire function, but you'll see the core parts that aren't working below.
function showscoreboard()
local function len(arg)
return string.len(arg)
end
local function tbuff(arg)
if len(arg) < 3 then
return arg.." "
else
return arg
end
end
local function sbuff(arg)
if len(arg) < 2 then
return " "..arg
else
return arg
end
end
local function cteam(t,s)
local status = s or nil
local forecolor = ""
if status == "p" then
forecolor = "yellow"
elseif status == "w" then
forecolor = "cyan"
else
forecolor = "limegreen"
end
return "<color fore="..forecolor..">"..t.."</color>"
end
local function bcolor(i)
local i = i or 0
if i%2 == 1 then
return "maroon"
else
return "navy"
end
end
local scorestring = ""
local allteams = {["ATL"]=0,["WAS"]=0,["MIA"]=0,["CLE"]=0,["OAK"]=0,["SD"]=0,["IND"]=0,["NYJ"]=0,["TEN"]=0,["SEA"]=0,["PHI"]=0,["DEN"]=0,["GB"]=0,["BUF"]=0,["TB"]=0,["PIT"]=0,["MIN"]=0,["HOU"]=0,["DET"]=0,["TB"]=0,["CAR"]=0,["CHI"]=0,["STL"]=0,["NYG"]=0,["ARI"]=0,["NO"]=0,["KC"]=0,["SF"]=0,["NE"]=0}
local byeweek = ""
for _,v in ipairs(nflscores.ss) do
allteams[v[5]] = 1
allteams[v[7]] = 1
end
for i,v in pairs(allteams) do
if v == 0 then
byeweek = byeweek .. "<color white>".. i .."</color>\r"
end
end
for i,v in ipairs(nflscores.ss) do
local hteam = v[7]
local ateam = v[5]
local qgame = v[3]
local hscre = v[8] or 0
local ascre = v[6] or 0
if v[4] then
qtime = "<color white>Time: "..v[4].."</color>"
else
qtime = ""
end
local gposs = v[9] or ""
if gposs ~= "" then
if gposs == hteam then
hteam = cteam(tbuff(hteam),"p")
ateam = cteam(tbuff(ateam))
else
ateam = cteam(tbuff(ateam),"p")
hteam = cteam(tbuff(hteam))
end
else
hteam = cteam(tbuff(hteam))
ateam = cteam(tbuff(ateam))
end
if qgame == "Final" or qgame == "final overtime" then
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam),"w")
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
if qgame == "Final" then
qgame = "<color cyan>F</color>"
elseif qgame == "final overtime" then
qgame = "<color cyan>F/OT</color>"
end
elseif qgame == "Pregame" then
qgame = "<color cyan>Pre</color>"
elseif qgame == "Halftime" then
qgame = "<color white>"..qgame.."</color>"
else
qgame = "<color white>Q"..qgame.."</color>"
end
scorestring = scorestring .. "<color back="..bcolor(i) .. ">".. v[1] .. ": " .. ateam .. "<color white>: " .. sbuff(ascre) .. "</color> <color black>#</color> " .. hteam .. "<color white>: ".. sbuff(hscre) .."</color></color> " .. qgame .. " " .. qtime .. "\r"
end
return scorestring .. "<color white>Bye week:</color>\r"..byeweek
end
The part that isn't working properly is:
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam),"w")
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
The function for cteam is:
local function cteam(t,s)
local status = s or nil
local forecolor = ""
if status == "p" then
forecolor = "yellow"
elseif status == "w" then
forecolor = "cyan"
else
forecolor = "limegreen"
end
return "<color fore="..forecolor..">"..t.."</color>"
end
Now, it colors the "p" status just fine. But when the status changes to "w", it fails, and for the life of me, I cannot figure out why. Am I missing something? Could this code be a lot cleaner?
Edit: I haven't found the issue to the problem, but apparently the "elseif status == "w" statement is completely bypassed. When the games are being played, the correct team in possession shows yellow. However, after the game is over, both teams are lime green, as if no score was higher than the other.
2nd Edit: The error listed in the first answer has been corrected. Still, it doesn't solve the issue. I'm still quite at a loss.
Nothing jumps out and I can't test here but here are some things to check:
You mention that cteam works correctly during the game, and that it's only once the game is over that cteam doesn't give the correct final result. So the logic of cteam is correct. The problem must be in the code that calls cteam: does cteam ever get called with s equals "w": this would never happen if hscre and ascre are always the same. Also there is a typo in the branch code that calls cteam:
if hscre > ascre then
hteam = cteam(tbuff(hteam),"w")
ateam = cteam(tbuff(ateam))
elseif hscre < ascre then
ateam = cteam(tbuff(ateam,"w")) -- ERR
hteam = cteam(tbuff(hteam))
else
ateam = cteam(tbuff(ateam))
hteam = cteam(tbuff(hteam))
end
The line that is tagged ERR should be:
ateam = cteam(tbuff(ateam),"w")
About cleaning up the code: post your question on StackOverflow's code review forum.
Related
In my research, I've encountered two possibilities for inserting a carriage return into a header in a VBA macro, using Chr(10) or Chr(13). I've even seen code posted by Allen Wyatt at excel.tips.com that seems to do exactly what I'm attempting, but where he asserts it works, I have yet to see success.
Here is the basic code I am attempting to execute:
With ActiveSheet.PageSetup
.CenterHeader = "&F" & Chr(10) & "&A"
End With
There is other formatting I'm doing, but it all succeeds. This line only produces the filename in the header ("&F"), but no return and no tab name on the second line. It also doesn't fail; it just continues right through this line.
This macro was originally recorded by me in Excel 2010, which I then augmented with additional automation for page formatting. I'm still running it under Excel 2010, and it has never worked correctly on this particular line. Does anyone have knowledge of what might be transpiring here?
Edit: Here is the full code from the original macro recording and my edits.
Application.PrintCommunication = False
With ActiveSheet.PageSetup
.PrintTitleRows = ""
.PrintTitleColumns = ""
End With
Application.PrintCommunication = True
ActiveSheet.PageSetup.PrintArea = ""
Application.PrintCommunication = False
With ActiveSheet.PageSetup
.PrintTitleRows = "$1:$1"
.PrintTitleColumns = ""
.LeftHeader = ""
.CenterHeader = "&F" & vbCrLf & "&A"
.RightHeader = ""
.LeftFooter = ""
.CenterFooter = ""
.RightFooter = "Printed &D"
.LeftMargin = Application.InchesToPoints(0.7)
.RightMargin = Application.InchesToPoints(0.7)
.TopMargin = Application.InchesToPoints(0.75)
.BottomMargin = Application.InchesToPoints(0.75)
.HeaderMargin = Application.InchesToPoints(0.3)
.FooterMargin = Application.InchesToPoints(0.3)
.PrintHeadings = False
.PrintGridlines = True
.PrintComments = xlPrintNoComments
.PrintQuality = 600
.CenterHorizontally = False
.CenterVertically = False
.Orientation = xlPortrait
.Draft = False
.PaperSize = xlPaperLetter
.FirstPageNumber = xlAutomatic
.Order = xlDownThenOver
.BlackAndWhite = False
.Zoom = 100
.PrintErrors = xlPrintErrorsDisplayed
.OddAndEvenPagesHeaderFooter = False
.DifferentFirstPageHeaderFooter = False
.ScaleWithDocHeaderFooter = True
.AlignMarginsHeaderFooter = True
.EvenPage.LeftHeader.Text = ""
.EvenPage.CenterHeader.Text = ""
.EvenPage.RightHeader.Text = ""
.EvenPage.LeftFooter.Text = ""
.EvenPage.CenterFooter.Text = ""
.EvenPage.RightFooter.Text = ""
.FirstPage.LeftHeader.Text = ""
.FirstPage.CenterHeader.Text = ""
.FirstPage.RightHeader.Text = ""
.FirstPage.LeftFooter.Text = ""
.FirstPage.CenterFooter.Text = ""
.FirstPage.RightFooter.Text = ""
End With
Application.PrintCommunication = True
Agree with Patrick H. This code works ...
Sub header()
With ActiveSheet.PageSetup
.CenterHeader = "&F" & vbCrLf & "&A"
End With
End Sub
I am trying to error check in a userform where I want to be able to check that the time that was entered is a valid time expression (00:00 or 00 PM) as I am sending it through a TimeValue command for the output so that the time is standardized. If the value entered is not a valid expression I will have an error message display and allow to reenter a valid expression. I am not sure if this is something I can accomplish with Regex or if there is a simpler option. I have attached my code below.
Private Sub CommandButton_OK_Click()
Dim emptyrow As Long
'Error Check
If NameText.Value = "" Then
MsgBox "Please Enter Valid Name", vbOKOnly
Exit Sub
End If
'Make Sheet 1 Active
Sheet1.Activate
'Determine emptyRow
emptyrow = WorksheetFunction.CountA(Range("E:E")) + 1
'Convert Time of Inspection to Time Value
TimeText.Value = TimeValue(TimeText.Value)
'Transfer Info
Cells(emptyrow, 5).Value = DateText.Value
Cells(emptyrow, 6).Value = NameText.Value
Cells(emptyrow, 7).Value = ShiftText.Value
Cells(emptyrow, 8).Value = TimeText.Value
If CornNo.Value = True Then
Cells(emptyrow, 9).Value = "No"
Else
Cells(emptyrow, 9).Value = "Yes"
End If
If SurgeNo.Value = True Then
Cells(emptyrow, 10).Value = "No"
Else
Cells(emptyrow, 10).Value = "Yes"
End If
If MillNo.Value = True Then
Cells(emptyrow, 11).Value = "No"
Else
Cells(emptyrow, 11).Value = "Yes"
End If
If FBedNo.Value = True Then
Cells(emptyrow, 12).Value = "No"
Else
Cells(emptyrow, 12).Value = "Yes"
End If
If DDGOutNo.Value = True Then
Cells(emptyrow, 13).Value = "No"
Else
Cells(emptyrow, 13).Value = "Yes"
End If
If DDGInNo.Value = True Then
Cells(emptyrow, 14).Value = "No"
Else
Cells(emptyrow, 14).Value = "Yes"
End If
Unload Me
End Sub
It looks like you may want to user error handling with the On Error GoTo Label statement, I think that this will get what you want done
Private Sub CommandButton_OK_Click()
If nameText.Value = "" Then GoTo InvalidName
'' Do some stuff
On Error GoTo InvalidTime
Let TimeText.Value = TimeValue(TimeText.Value)
On Error GoTo 0
'' Do some more stuff
Let Cells(emptyrow, 9).Value = IIf(CornNo.Value = True, "No", "Yes")
'' Do even more stuff
Exit Sub
InvalidName:
MsgBox "Please Enter a Name", vbInformation + vbOKOnly, "Error"
Exit Sub
InvalidTime:
MsgBox "Please Enter a Valid Time", vbInformation + vbOKOnly, "Error"
Exit Sub
End Sub
I having issues with the def check guess. It's the format my teacher specifically gave. You guys are great. Thanks for the help!!!! Sorry for the format this is my first time on this site.
# # Global variables
wrong_guesses = []
target_phrase = ""
current_phrase = ""
def clear_display():
for i in range(20):
print "\n"
def string_with_dashes(str):
global target_phrase
new_phrase = ""
for i in str:
if i.isalpha():
new_phrase += "-"
else:
new_phrase += i
return new_phrase
def check_guess(letter):
global current_phrase
replacement_list = [""]
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
current_phrase = replacement_list
return current_phrase
else:
wrong_guesses.append(letter)
return False
def process_input():
user_letter = raw_input("Guess a letter: ").upper()
if user_letter in wrong_guesses:
print "You already guessed that letter"
user_letter = raw_input("Guess again : ")
else:
return check_guess(user_letter)
def one_turn():
global wrong_guesses
print "=================================================="
print current_phrase
print "Wrong guesses:", ' '.join(wrong_guesses)
print "Guesses remaining:", (8 - len(wrong_guesses))
display_robot(8 - len(wrong_guesses))
print "String to guess:", current_phrase
print "=================================================="
process_input()
print "\n\n"
def setup_phrase():
global target_phrase, current_phrase
target_phrase = raw_input("Dear friend, enter a phrase for the user to guess: ").upper()
current_phrase = string_with_dashes(target_phrase)
setup_phrase()
clear_display()
while True:
one_turn()
if len(wrong_guesses) > 7:
print "GAME OVER! You Lose"
breack
if current_phrase == target_phrase:
print "You WIN!!"
break
(why won't stackoverflow let me fix your code?)
I'm not sure exactly what you are trying to do, but it sounds like you want to create a string where the guessed letters replace blanks as they are guessed? Try something like this:
hidden_phrase = "abracadabra"
current_list = ["."]*len(hidden_phrase)
def check_guess(letter):
for i in range(len(hidden_phrase)):
if hidden_phrase[i] == letter:
current_list [i] = hidden_phrase[i]
print("before", "".join(current_list ))
check_guess("a")
print("guess1", "".join(current_list))
check_guess("z")
print("guess2", "".join(current_list))
check_guess("b")
print("guess3", "".join(current_list))
Output:
before ...........
guess1 a..a.a.a..a
guess2 a..a.a.a..a
guess3 ab.a.a.ab.a
In Python strings are immutable, and can't be updated, so it seems easier to me to keep the 'replacement' word (with blanks, which I represent with .) as a list, and join it back together for display.
The two global variables don't need to be explicitly specified as global, because the variable is not assigned to in the function, only accessed.
If you prefer to have a string current_phrase and update that, of course that's possible too:
hidden_phrase = "abracadabra"
current_phrase = "."*len(hidden_phrase )
def check_guess(letter):
global current_phrase
i = -1
while True:
i = hidden_phrase.find(letter, i+1)
if i<0:
break
current_phrase = current_phrase[0:i]+letter + current_phrase[i+1:]
print("before", current_phrase)
check_guess("a")
print("guess1", current_phrase)
check_guess("z")
print("guess2", current_phrase)
check_guess("b")
print("guess3", current_phrase)
This time you need the global again to prevent current_phrase = ... from creating a local variable.
My previous answer was to the first, more general, version of your question. Several things were wrong with your check_guess(). Here's a fixed version:
def check_guess(letter):
global current_phrase
replacement_list = list(current_phrase)
found=False
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
found = True
if found:
current_phrase = "".join(replacement_list)
else:
wrong_guesses.append(letter)
Comments to show problems with your version:
def check_guess(letter):
global current_phrase
replacement_list = [""] # list has only 1 element, can't assign above index zero
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
current_phrase = replacement_list # assigning a list to what was previously a string
return current_phrase # returns before checking 2nd character
else:
wrong_guesses.append(letter) # only the first character has been checked
return False # returns False or current_phrase, inconsistent
Also near the end you wrote breack instead of break, it's a shame that Python doesn't check these things by default, waiting instead for you to hit that line.
I am trying to simplify the following program code which actually works. The intention is to search for a string to be specified in a text file (log file) and output these lines but also 5 lines prior and behind this line. If in the 5 lines behind the matching line the search string occurs again it must be avoided that the lines will be displayed or exported more than once. Any tips are much appreciated.
def analyze(search_string, outdev):
file = "infile.txt"
print "investigating file: " + file + " ..."
line1 = ""
line2 = ""
line3 = ""
line4 = ""
line5 = ""
line6 = ""
n = 0
output = 0
if outdev == "s": ### output: screen
data = open(file, "r")
for line in data.readlines():
line6 = line5
line5 = line4
line4 = line3
line3 = line2
line2 = line1
line1 = line
if line.find(search_string) != -1 and output == 0:
output = 1
print ""
print "-" * 80
print ""
print line6
print line5
print line4
print line3
print line2
print ""
print "." * 20
print ""
n = 1
changed = 1
found = 1
if output == 1 and 1 <= n <= 6 :
if line.find(search_string) != -1:
if found == 0:
changed = 1
else:
changed = 0
found = 1
else:
if found == 1:
changed = 1
else:
changed = 0
found = 0
if changed == 1:
print ""
print "." * 20
print ""
changed = 0
print line
n += 1
if line.find(search_string) != -1:
n = 1
if n == 6:
n = 0
output = 0
data.close()
if outdev == "f": ### output: file
out_file = "outfile.txt"
out_f = open(out_file, "w")
data = open(file, "r")
for line in data.readlines():
line6 = line5
line5 = line4
line4 = line3
line3 = line2
line2 = line1
line1 = line
if line.find(search_string) != -1 and output == 0:
output = 1
out_f.write(lf + "-" * 128 + lf + lf)
out_f.write(line6)
out_f.write(line5)
out_f.write(line4)
out_f.write(line3)
out_f.write(line2)
out_f.write(lf + "." * 20 + lf + lf)
n = 1
changed = 1
found = 1
if output == 1 and 1 <= n <= 6 :
if line.find(search_string) != -1:
if found == 0:
changed = 1
else:
changed = 0
found = 1
else:
if found == 1:
changed = 1
else:
changed = 0
found = 0
if changed == 1:
out_f.write(lf + "." * 20 + lf + lf)
changed = 0
out_f.write(line) # output recent line
n += 1 # increase counter
if line.find(search_string) != -1: # Search String found : reset counter
n = 1
if n == 6:
n = 0
output = 0
data.close()
out_f.close()
...
As asked by inspectorG4dget :
"changed" is a flag to store the state of the previous line in order to control the the output of the interlines ("." * 20).
Please find the comments to see is how it works:
if line.find(search_string) != -1: ## does the recent line contain the search string:
## => Yes:
if found == 0: ## was there a match in the previous line?
changed = 1 ## => No: the state has changed
else:
changed = 0 ## => Yes: the state didn't change
found = 1 ## store the state of the recent line in the found-flag
else: ## => No:
if found == 1: ## was there a match in the previous line?
changed = 1 ## => Yes: the state has changed
else:
changed = 0 ## => No: the state didn't change
found = 0 ## store the state of the recent line in the found-flag
Alright, this is what I would do:
class Buffer:
def __init__(self, size):
self.buffer = []
self.size = size
def add(self, elem):
if len(self.buffer) == self.size:
self.buffer.pop(0)
self.buffer.append(elem)
def getElems(self):
for elem in self.buffer:
yield elem
def analyze(search_string):
buffer = Buffer(5)
with open("infile.txt") as infile:
for line in infile:
line = line.strip()
if search_string in line:
if any(search_string in l for l in buffer): continue
print '-'*80
for e in buffer.getElems(): print e
print '.'*20
print line
buffer.add(line)
if __name__ == "__main__": analyze("search_string")
Once you have this, then you can decide where to send the output like this:
Send it to the screen:
$ python my_script.py
Send it to a file:
$ python my_script.py > some_file.txt
Spent a week trying to figure this out, so far, so I'm not just jumping here first - and all Microsoft sites tend to focus on Excel which seems to be non-appropriate for what I'm doing:
I'm attempting to use this VBA script to open up multiple WORD files, in succession, run a Find/Selection to grab a specific pattern, and then copy all occurrences into another WORD file.
This code is a mix of something I found online (though can't recall where, at this point) and my own tinkering. I've been able to DEBUG.PRINT the correct output, but no way to continue to move through my file to copy specific lines and then paste them. I feel it has something to do with the .Activate calls:
Sub x()
Dim GetStr(5000) As String
Const wdStory = 4
Const wdExtend = 1
'Set Doc = Documents.Open(FileName:="C:\Users\...\filename.CDS", Visible:=True)
'Set Doc = Documents.Open("C:\Users\...\filename.CDS")
Set MyDialog = Application.FileDialog(msoFileDialogFilePicker)
With MyDialog
.Filters.Clear
.Filters.Add "All WORD File ", "*.CDS", 1
.AllowMultiSelect = True
i = 2 'set to 2 in order to offset the open word window that houses the VBA
If .Show = -1 Then
For Each stiSelectedItem In .SelectedItems
GetStr(i) = stiSelectedItem
i = i + 1
Next
i = i - 1
End If
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open ("C:\Users\...\filename.docx")
For j = 2 To i Step 1
Set objDoc = objWord.Documents.Open(GetStr(j))
'Debug.Print (objWord.Documents(1).Name)
Set objSelection = objWord.Selection
objSelection.Find.Forward = True
objSelection.Find.MatchWildcards = True
objSelection.Find.Text = "DEFINE"
Do While True
objSelection.Find.Execute
Debug.Print (objSelection)
If objSelection.Find.Found Then
objSelection.EndOf wdStory, wdExtend 'get selection
strText = objSelection.Copy 'strText = selection copied to clipboard, no value (like an inline function)
Set selectionToPaste = objWord.Selection 'selectionToPaste is literally the clipboard
'objWord.Documents(2).Activate
'Debug.Print ("->'Activated Window': " + objWord.ActiveDocument.Name)
'Debug.Print ("selectionToPaste = " + selectionToPaste)
selectionToPaste.Paste
'objWord.Documents(1).Activate
objSelection.Find.Execute
Else
objWord.ActiveDocument.Save
objWord.ActiveWindow.Close
Exit Do
End If
Loop
Next
End With
End Sub
OP here - Solved my own problem utilizing a loop.
Sub x()
Dim GetStr(5000) As String
**Dim iCounter As Integer**
Const wdStory = 4
Const wdExtend = 1
'Set Doc = Documents.Open(FileName:="C:\Users\...\filename.CDS", Visible:=True)
'Set Doc = Documents.Open("C:\Users\...\filename.CDS")
Set MyDialog = Application.FileDialog(msoFileDialogFilePicker)
With MyDialog
.Filters.Clear
.Filters.Add "All WORD File ", "*.CDS", 1
.AllowMultiSelect = True
i = 2 'set to 2 in order to offset the open word window that houses the VBA
If .Show = -1 Then
For Each stiSelectedItem In .SelectedItems
GetStr(i) = stiSelectedItem
i = i + 1
Next
i = i - 1
End If
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Open ("C:\Users\lidm3b2\Desktop\gar\2.docx")
For j = 2 To i Step 1
Set objDoc = objWord.Documents.Open(GetStr(j))
'Debug.Print (objWord.Documents(1).Name)
Set objSelection = objWord.Selection
objSelection.Find.Forward = True
objSelection.Find.MatchWildcards = True
objSelection.Find.Text = "DEFINE"
**iCounter = 0**
Do While True
**For iLoopCounter = 0 To iCounter Step 1
objSelection.Find.Execute
Next**
Debug.Print (objSelection)
If objSelection.Find.Found Then
objSelection.EndOf wdStory, wdExtend 'get selection
strText = objSelection.Copy 'strText = selection copied to clipboard, no value (like an inline function)
Set selectionToPaste = objWord.Selection 'selectionToPaste is literally the clipboard
objWord.Documents(2).Activate
'Debug.Print ("->'Activated Window': " + objWord.ActiveDocument.Name)
'Debug.Print ("selectionToPaste = " + selectionToPaste)
objWord.Selection.Paste
objWord.Documents(1).Activate
**iLoopCounter = iLoopCounter + 1**
objSelection.Find.Execute
Else
objWord.ActiveDocument.Save
objWord.ActiveWindow.Close 'have to close for the hardcode on "...Documents(1)..." and 2 to work.
Exit Do
End If
Loop
Next
End With
End Sub