Concat in Arrayformula using row numbers - if-statement

UPDATE - Modified answer
With help from #player0, found solution that handled line seperators too:
=ARRAYFORMULA(REGEXREPLACE(TRANSPOSE(QUERY(TRANSPOSE(SPLIT(TRANSPOSE(SPLIT(QUERY( IF(D1:D="[task]", "♦"&D1:D, "♣♀"&D1:D),,999^99), "♦", )), "♀")),,999^99)),"\s*♣\s*",char(10)))
This moves each [task] section into its own cell, retaining all other formatting, and stops the extra whitespace that gets added around each cells content that are joined/concat together.
Original Post
Can't seem to find anywhere else this is done, so happy for any links in comments too :)
I have a column of text, the contents of over a hundred files with [task] at top of each.
More than 50,000 characters, so they pasted into a newline each cell ('paste as values').
I can easily tell the row numbers to work with and have a draggable working formula, just can't get it properly ARRAYFORMULA capable, since the input might change by easily a thousand rows so needs to handle that gracefully.
Formulas only please, no code
Example Spreadsheet
https://docs.google.com/spreadsheets/d/1yaETa3Pvq47DpcAyojSlf6p5N1Tt_hpvoqp7WEtC6pI/edit?usp=sharing
Example Input (50,000+ characters)
https://drive.google.com/file/d/1sMl0ZQfbXZUjpB0fic2VkX5Ze5H_IEGL/view?usp=sharing
Note - if the input file is removed when I clean my drive up, just copy-paste the sample below till 50,000+ characters, or see linked spreadsheet
Input
[task]
SpriteNE = floor_metal_01.dds
SpriteSE = floor_metal_01.dds
SpriteSW = floor_metal_01.dds
SpriteNW = floor_metal_01.dds
guilevel = 1
guiindex = 10
type = COMPONENT
locked = 0
name = category_advanced_manufacturing
parent
[task]
SpriteNE = floor_metal_01.dds
SpriteSE = floor_metal_01.dds
SpriteSW = floor_metal_01.dds
SpriteNW = floor_metal_01.dds
guilevel = 1
guiindex = 9
type = COMPONENT
locked = 0
name = category_facilities
parent
[task]
tilelable
SpriteNE = conveyor_NE.dds
SpriteSE = conveyor_SE.dds
SpriteSW = conveyor_SW.dds
SpriteNW = conveyor_NW.dds
exitdirectionoffsets = 0
inputdirectionoffsets = 2
guilevel = 1
parent
guiindex = 0.5
name = task_conveyor
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_SE.dds
[task]
tilelable
SpriteNE = conveyor_converge3_NE.dds
SpriteSE = conveyor_converge3_SE.dds
SpriteSW = conveyor_converge3_SW.dds
SpriteNW = conveyor_converge3_NW.dds
exitdirectionoffsets = 0,
inputdirectionoffsets = 1,2,3
guilevel = -1
parent
guiindex = 1
name = task_conveyor_converge3
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_converge3_SE.dds
[task]
tilelable
SpriteNE = conveyor_crossover_NE.dds
SpriteSE = conveyor_crossover_SE.dds
SpriteSW = conveyor_crossover_SW.dds
SpriteNW = conveyor_crossover_NW.dds
exitdirectionoffsets = 0,3
inputdirectionoffsets = 1,2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_crossover
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_crossover_SE.dds
[task]
tilelable
SpriteNE = conveyor_left_NE.dds
SpriteSE = conveyor_left_SE.dds
SpriteSW = conveyor_left_SW.dds
SpriteNW = conveyor_left_NW.dds
exitdirectionoffsets = 3
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_left
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_left_SE.dds
[task]
tilelable
SpriteNE = conveyor_right_NE.dds
SpriteSE = conveyor_right_SE.dds
SpriteSW = conveyor_right_SW.dds
SpriteNW = conveyor_right_NW.dds
exitdirectionoffsets = 1
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_right
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_right_SE.dds
[task]
tilelable
SpriteNE = conveyor_split3_NE.dds
SpriteSE = conveyor_split3_SE.dds
SpriteSW = conveyor_split3_SW.dds
SpriteNW = conveyor_split3_NW.dds
exitdirectionoffsets = 0,1,3
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_split3
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_split3_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_NE.dds
SpriteSE = conveyor_t_SE.dds
SpriteSW = conveyor_t_SW.dds
SpriteNW = conveyor_t_NW.dds
exitdirectionoffsets = 3,1
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_join_NE.dds
SpriteSE = conveyor_t_join_SE.dds
SpriteSW = conveyor_t_join_SW.dds
SpriteNW = conveyor_t_join_NW.dds
exitdirectionoffsets = 0
inputdirectionoffsets = 1,3
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t_join
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_join_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_join_left_NE.dds
SpriteSE = conveyor_t_join_left_SE.dds
SpriteSW = conveyor_t_join_left_SW.dds
SpriteNW = conveyor_t_join_left_NW.dds
exitdirectionoffsets = 0
inputdirectionoffsets = 2,3
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t_join_left
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_join_left_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_join_right_NE.dds
SpriteSE = conveyor_t_join_right_SE.dds
SpriteSW = conveyor_t_join_right_SW.dds
SpriteNW = conveyor_t_join_right_NW.dds
exitdirectionoffsets = 0
inputdirectionoffsets = 1,2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t_join_right
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_join_right_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_left_NE.dds
SpriteSE = conveyor_t_left_SE.dds
SpriteSW = conveyor_t_left_SW.dds
SpriteNW = conveyor_t_left_NW.dds
exitdirectionoffsets = 0,3
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t_left
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_left_SE.dds
[task]
tilelable
SpriteNE = conveyor_t_right_NE.dds
SpriteSE = conveyor_t_right_SE.dds
SpriteSW = conveyor_t_right_SW.dds
SpriteNW = conveyor_t_right_NW.dds
exitdirectionoffsets = 0,1
inputdirectionoffsets = 2
guilevel = -1
parent
guiindex = 1
name = task_conveyor_t_right
is_conveyor = 1
[components]
[resources]
[subtasksrequired]
[subtasksapplied]
[tile]
texture = conveyor_t_right_SE.dds
Desired Output
Each [task].* is a new file, so seperate by those into one cell each in a single column, with newlines (\n) as internal separators.
In other words, everything after [task] till the next [task] (or end of column, if no more [task]) combined into one cell each.
Just has to be arrayformula able and avoid the char limit for functions like concat of 50,000 characters.
Current Output
Getting row numbers
$D$1:D is the input column
$G$1 is dropdown with "[task]" selected
$M$1 =ARRAYFORMULA(QUERY({$D1:$D, row($D1:$D)},"select * where Col1 = '"&$G$1&"'"))
$O$1 =ARRAYFORMULA(QUERY({$M1:$M,{$M2:$M;0}},"select *"))
Then some of my attempts to use these numbers
Works, has to be dragged through, and doesn't have any separators.
=ARRAYFORMULA(CONCATENATE(INDIRECT("$D"&$O1:$O&":$D"&$P1:$P-1)))
Doesn't work, I kept adding more arrayformula but still just first result
=ARRAYFORMULA(IF($P1:P<>"",CONCATENATE(ARRAYFORMULA(INDIRECT("$D"&ARRAYFORMULA(INDIRECT("$O"&IF($P1:$P<>"",row($P1:$P),"")&":$O"))&":$D"&ARRAYFORMULA(INDIRECT("$P"&IF($P1:$P<>"",row($P1:$P),"")&":$P"))-1))),""))
Just the string used in previous INDIRECT
=ARRAYFORMULA(IF($O1:O<>"","$D"&ARRAYFORMULA(INDIRECT("$O"&IF($P1:$P<>"",row($P1:$P),"")&":$O"))&":$D"&ARRAYFORMULA(INDIRECT("$P"&IF($P1:$P<>"",row($P1:$P),"")&":$P"))-1,""))
Doesn't work, has separators but still only looping the first result.
$U1:U is the string list for indirects (see above)
=ARRAYFORMULA(IF($U1:U<>"",TEXTJOIN(";",FALSE,INDIRECT($U1:U)),""))
There are some other formulas in the example sheet, I mostly removed the duds as I kept going though.
I found lots of interesting resources out there but nothing that seemed to target using row numbers, or even just SPLIT + JOIN type approach that allowed ARRAYFORMULA (AND avoided the 50,000 character limit issue with single CONCAT or similar calls).

try:
=ARRAYFORMULA(SPLIT(TRANSPOSE(SPLIT(QUERY(
IF(A2:A="[task]", "♦"&A2:A, "♀"&A2:A),,999^99), "♦", )), "♀"))

This is sample as I said before in comment, you just call function in cell "=GroupMacro" unfortunately, this can't be auto refresh:
var rtrn=[];
var rslt=[];
var rslt2='';
function GroupMacro() {
var spreadsheet = SpreadsheetApp.getActive();
var bomo=spreadsheet.getRange('D1:D' + spreadsheet.getLastRow()).getValues();
for (a=0; a<bomo.length; a++)
{
if(bomo[a]=='test') //this is separator, this can be applied as parameter in function
{
if(a>0)
{
rslt2=rslt.join();
rtrn.push(rslt2);
rslt=[];
}
rslt.push(bomo[a]);
}
else
{
rslt.push(bomo[a]);
}
}
rslt2=rslt.join();
rtrn.push(rslt2);
return rtrn;
};

Related

link color clashes with background using MAGNIFY ODS style

I recently switched from the HTML destination to HTML5 so I would get SVG graphics in a job, and everything looks lovely, except my table-of-contents links, which now have bad contrast against the dark background produced by the MAGNIFY style. Dig how ugly these things are:
My call is:
ods html5 path = "&qa_folder" (URL=NONE)
body = "ute_graphs.html"
contents = "toc.html"
frame = "index.html"
(title = "VDW Utilization Dataset Record Counts")
style = magnify
nogfootnote
nogtitle
device = svg
options(svg_mode="embed")
;
What's the easiest way I can recolor those (without ditching MAGNIFY)?
This generates the template:
proc template;
source styles.magnify;
run;
Which is as follows:
proc template;
define style Styles.Magnify_CUSTOM;
parent = styles.default;
style fonts /
'TitleFont2' = ("Verdana, Helvetica, <sans-serif>, sans-serif",14pt,bold)
'TitleFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",18pt,bold)
'StrongFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",14pt,bold)
'EmphasisFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",10pt,italic)
'FixedEmphasisFont' = ("<monospace>, Courier, monospace",10pt,italic)
'FixedStrongFont' = ("<monospace>, Courier, monospace",10pt,bold)
'FixedHeadingFont' = ("<monospace>, Courier, monospace",10pt)
'BatchFixedFont' = ("SAS Monospace, <monospace>, Courier, monospace",10pt)
'FixedFont' = ("<monospace>, Courier, monospace",10pt)
'headingEmphasisFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",14pt,bold italic)
'headingFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",14pt,bold)
'docFont' = ("Verdana, Helvetica, <sans-serif>, sans-serif",8pt,bold);
class GraphFonts /
'GraphDataFont' = ("Verdana, <MTsans-serif>",7pt)
'GraphUnicodeFont' = ("<MTsans-serif-unicode>",9pt)
'GraphFootnoteFont' = ("Verdana, <MTsans-serif>",10pt,bold)
'GraphTitleFont' = ("Verdana, <MTsans-serif>",11pt,bold)
'GraphTitle1Font' = ("Verdana, <MTsans-serif>",14pt,bold)
'GraphValueFont' = ("Verdana, <MTsans-serif>",9pt)
'GraphLabel2Font' = ("Verdana, <MTsans-serif>",10pt)
'GraphLabelFont' = ("Verdana, <MTsans-serif>",10pt,bold)
'GraphAnnoFont' = ("Verdana, <MTsans-serif>",10pt);
style colors /
'headerfgemph' = cxFFFFFF
'headerbgemph' = cx387BB1
'headerfgstrong' = cxFFFFFF
'headerbgstrong' = cx387BB1
'headerfg' = cxFFFFFF
'headerbg' = cx387BB1
'datafgemph' = cxFFFFFF
'databgemph' = cx224764
'datafgstrong' = cxFFFFFF
'databgstrong' = cx224764
'datafg' = cxFFFFFF
'databg' = cx285375
'batchfg' = cxFFFFFF
'batchbg' = cx224764
'tableborder' = cxFFFFFF
'tablebg' = cx000000
'notefg' = cxFFFFFF
'notebg' = cx224764
'bylinefg' = cxFFFFFF
'bylinebg' = cx224764
'captionfg' = cxFFFFFF
'captionbg' = cx224764
'proctitlefg' = cxFFFFFF
'proctitlebg' = cx224764
'titlefg' = cxFFFFFF
'titlebg' = cx224764
'systitlefg' = cxFFFFFF
'systitlebg' = cx224764
'Conentryfg' = cxFFFFFF
'Confolderfg' = cxFFFFFF
'Contitlefg' = cxFFFFFF
'link2' = cxE3BC61
'link1' = cxFEEDA2
'contentfg' = cxFFFFFF
'contentbg' = cx224764
'docfg' = cxFFFFFF
'docbg' = cx224764;
class GraphColors /
'gblockheader' = colors('docbg')
'gcphasebox' = CXFFFFFF
'gphasebox' = cxC2C9D8
'gczonec' = cxB7C2DA
'gzonec' = cxCBD3E3
'gczoneb' = cxC0CBE4
'gzoneb' = cxD2D9E9
'gzonea' = cxDBE2F1
'gcmiss' = cx84929e
'gmiss' = cx4c687f
'gablock' = colors('docbg')
'gblock' = colors('docbg')
'gcclipping' = cxDC531F
'gclipping' = cxE7774F
'gcstars' = cxFFFFFF
'gstars' = cx2B599B
'gcruntest' = cxBF4D4D
'gruntest' = cxCAE3FF
'gccontrollim' = cxFFFFFF
'gcontrollim' = cx2B599B
'gcerror' = cxFFFFFF
'gerror' = cx2B599B
'gcpredictlim' = cxACC1D8
'gpredictlim' = cx2B599B
'gcpredict' = cxACC1D8
'gpredict' = cxACC1D8
'gcconfidence2' = cxC9BDA0
'gcconfidence' = cxACC1D8
'gconfidence2' = cx9B7F2B
'gconfidence' = cx2B599B
'gcfit2' = cxC9BDA0
'gcfit' = cxACC1D8
'gfit2' = cxC9BDA0
'gfit' = cxACC1D8
'gcoutlier' = cxFFFFFF
'goutlier' = cx2B599B
'gcdata' = cxFFFFFF
'gdata' = cx2B599B
'ginsetheader' = colors('docbg')
'ginset' = CX2E7787
'greferencelines' = cxB9B9B9
'gheader' = colors('docbg')
'gout2cend' = cx3B82BC
'gout2cstart' = cxFFFFFF
'gconramp3cend' = cxE2746C
'gconramp3cneutral' = cxE5E9EE
'gconramp3cstart' = cx4FA3E7
'gramp3cend' = cx7570B3
'gramp3cneutral' = cxD95F02
'gramp3cstart' = cxE3BC61
'gconramp2cend' = cx99CCFF
'gconramp2cstart' = cxFFFFFF
'gramp2cend' = cx3B82BC
'gramp2cstart' = cxFFFFFF
'gtext' = CXFFFFFF
'glabel' = CXFFFFFF
'gborderlines' = CXFFFFFF
'goutlines' = CXFFFFFF
'gmgrid' = cx3E5C74
'ggrid' = CX5F7D95
'gaxis' = CXFFFFFF
'gshadow' = CX000000
'glegend' = CX173750
'gfloor' = CX173750
'gwalls' = cx173750
'gckran5' = cx96CC64
'gkran5' = cx7BB04A
'gckran4' = cxD5E864
'gkran4' = cxB8CC49
'gckran3' = cxFFF567
'gkran3' = cxF2D94B
'gckran2' = cxFFAE5F
'gkran2' = cxE09346
'gckran1' = cxF0735D
'gkran1' = cxD15845
'gcdata12' = cxD9E168
'gcdata11' = cxE2746C
'gcdata10' = cx5A82AB
'gcdata9' = cx956FC3
'gcdata8' = cxC08C59
'gcdata7' = cx9E6671
'gcdata6' = cxE5E9EE
'gcdata5' = cx79BD87
'gcdata4' = cxFFF1B7
'gcdata3' = cxB4BDEA
'gcdata2' = cxFFD472
'gcdata1' = cx4FA3E7
'gdata12' = CXB6BC56
'gdata11' = CXBD6059
'gdata10' = CX3A5C7E
'gdata9' = CX64559D
'gdata8' = CXBE8A57
'gdata7' = CX73434C
'gdata6' = CXE0E4E7
'gdata5' = CX5E996A
'gdata4' = CXFEEDA2
'gdata3' = CXAAB1D7
'gdata2' = CXE3BC61
'gdata1' = CX3B82BC;
style Table from Output /
cellpadding = 5
borderwidth = 2
bordercollapse = separate
borderstyle = solid;
style GraphCharts from GraphCharts
"Chart Attributes" /
transparency = 0.15;
style GraphLabelText from GraphLabelText
"Label attributes" /
dropshadow = on;
style GraphLabel2Text from GraphLabel2Text
"Label attributes" /
dropshadow = on;
style GraphValueText from GraphValueText
"Value attributes" /
dropshadow = on;
style GraphBackground from GraphBackground
"Graph background attributes" /
image = "Magnify.gif"
textalign = left
verticalalign = top;
style GraphWalls from GraphWalls
"Wall Attributes" /
transparency = 1.0;
style GraphLegendBackground from GraphLegendBackground
"Legend Background Attributes" /
transparency = 1.0;
style GraphOther from GraphData12;
style GraphInitial from GraphData11;
style GraphFinal from GraphData12;
style GraphOverflow from GraphData11;
style GraphUnderflow from GraphData12;
end;
run;
You can then play around with LINK1/LINK2 and use the MAGNIFY_CUSTOM as your style. If this doesn't work let me know and I'll test out the other way of modifying the template via a CLASS. The colour codes are in the format of hex codes, preceded by CX.

My entry widget replaces the item in the list instead of adding as a new item?

Instead of appending the job_list entry to the list, it replaces the item before when you try to input a new value. I think you can mainly focus on the store_job method, the job number entry and the enter job button. I'm not sure if I need a reset method or something so that the Entry widgets can take more data. Any help would be much appreciated.
from tkinter import *
class EntryGUI:
def __init__(self, parent):
self.cb = IntVar()
self.job_number_label= Label(parent, text = "Job number:")
self.job_number_label.grid(row = 1, column = 0)
self.job_number = Entry(parent)
self.job_number.focus()
self.job_number.grid(row=1, column = 1)
self.customer_name_label = Label(parent, text = "Customer name:")
self.customer_name_label.grid(row = 2, column = 0)
self.customer_name = Entry(parent)
self.customer_name.grid(row=2, column = 1)
self.distance_label= Label(parent, text = "Distance Travelled (km):")
self.distance_label.grid(row = 3, column = 0)
self.distance = Entry(parent)
self.distance.grid(row=3, column = 1)
self.min_spent_label= Label(parent, text = "Minutes spent on Virus protection:")
self.min_spent_label.grid(row = 4, column = 0)
self.min_spent = Entry(parent)
self.min_spent.grid(row=4, column = 1)
wof_tune= Checkbutton(parent, variable = self.cb, text = "check if WOF and tune is required",
onvalue = 100, offvalue = 0)
wof_tune.grid(row = 5, column = 0)
self.enter = Button(parent, text = "Enter Job", command = lambda:[self.store_job(),self.calculate()])
self.enter.grid(row = 6, column = 0)
self.show_all = Button(parent, text = "Show All")
self.show_all.grid(row = 6, column = 1)
def store_job(self):
self.job_list = []
self.customer_list = []
self.job_list.append(self.job_number.get())
self.customer_list.append(self.customer_name.get())
for i in self.job_list:
print (i)
def calculate(self):
self.cost_list = []
self.distance_calc = int(self.distance.get())
self.min_calc = int(self.min_spent.get())
self.cost = 0
#calculates the travel cost
#if the distance is less than 5km it costs 10
if self.distance_calc <= 5:
self.cost = 10
else:
self.distance_calc = self.distance_calc - 5 #-5 as you calclate the extra distance
self.distance_calc = self.distance_calc / 2 #divide by two as you add 50c per km
self.cost = self.distance_calc + 10 #initial 10 plus half the extra distance
#print(self.cost)
self.cost = self.cost + (self.min_calc * 0.8)
self.cost = self.cost + int(self.cb.get())
self.cost_list.append(self.cost)
print(self.cost_list)
self.enter_next()
def enter_next(self):
self.job_number.delete(0,END)
self.customer_name.delete(0, END)
self.distance.delete(0, END)
self.min_spent.delete(0, END)
self.enter.configure(state = NORMAL)
if __name__=="__main__":
root = Tk()
show_label = EntryGUI(root)
root.mainloop()
You were resetting the lists used to store the data entered every time the data is entered; you need to declare storage attributes in __init__, then use them to accumulate the data:
class EntryGUI:
def __init__(self, parent):
self.cb = IntVar()
self.job_number_label = Label(parent, text="Job number:")
self.job_number_label.grid(row=1, column=0)
self.job_number = Entry(parent)
self.job_number.focus()
self.job_number.grid(row=1, column=1)
self.customer_name_label = Label(parent, text="Customer name:")
self.customer_name_label.grid(row=2, column=0)
self.customer_name = Entry(parent)
self.customer_name.grid(row=2, column=1)
self.distance_label = Label(parent, text="Distance Travelled (km):")
self.distance_label.grid(row=3, column=0)
self.distance = Entry(parent)
self.distance.grid(row=3, column=1)
self.min_spent_label = Label(parent, text="Minutes spent on Virus protection:")
self.min_spent_label.grid(row=4, column=0)
self.min_spent = Entry(parent)
self.min_spent.grid(row=4, column=1)
wof_tune= Checkbutton(parent, variable=self.cb, text="check if WOF and tune is required",
onvalue =100, offvalue=0)
wof_tune.grid(row=5, column=0)
self.enter = Button(parent, text="Enter Job", command=self.acquire_entries)
self.enter.grid(row=6, column=0)
self.show_all = Button(parent, text="Show All")
self.show_all.grid(row=6, column=1)
self.job_list = []
self.customer_list = []
self.cost_list = []
def acquire_entries(self):
self.store_job()
self.calculate()
def store_job(self):
self.job_list.append(self.job_number.get())
self.customer_list.append(self.customer_name.get())
def calculate(self):
self.distance_calc = int(self.distance.get())
self.min_calc = int(self.min_spent.get())
self.cost = 0
# ... unchanged below

Tkinter grid in Gender option

How we set the grid for gender so that they will be close to 2 columns only.
I want gender(label), male and female(options) are packed into 2 columns.
Here is my code...
from Tkinter import *
root = Tk()
root.geometry('500x500')
root.title('Registration Form')
head = Frame(root)
entry = Frame(root)
head.pack()
entry.pack()
var = StringVar()
heading = Label(head,text='Registration Form',font='Helvetica 25 bold',pady=10).pack()
name_label = Label(entry,text='Name ',font='Helvetica 10 bold',pady=5)
name_entry = Entry(entry,width=30, font='Helvetica 10')
email_label = Label(entry,text='Email ',font='Helvetica 10 bold',pady=5)
email_entry = Entry(entry,width=30, font='Helvetica 10')
mob_label = Label(entry,text='Mobile ',font='Helvetica 10 bold',pady=5)
mob_entry = Entry(entry,width=30, font='Helvetica 10')
gender_label = Label(entry,text='Gender ',font='Helvetica 10 bold',pady=5)
male = Radiobutton(entry,text='Male',variable=var,value='male')
female = Radiobutton(entry,text='Female',variable=var,value='female')
name_label.grid(row=1, column=1)
name_entry.grid(row=1, column=2)
email_label.grid(row=2, column=1)
email_entry.grid(row=2, column=2)
mob_label.grid(row=3, column=1)
mob_entry.grid(row=3, column=2)
gender_label.grid(row=4, column=1)
male.grid(row=4,column=2, sticky="nsew")
female.grid(row=4,column=2,sticky="nsew")
root.mainloop()
Put male or female in next column and use columnspan=2 for Entry
from tkinter import *
root = Tk()
name_label = Label(root, text='Name')
name_entry = Entry(root)
gender_label = Label(root, text='Gender')
male = Radiobutton(root, text='Male')
female = Radiobutton(root, text='Female')
name_label.grid(row=1, column=1)
name_entry.grid(row=1, column=2, columnspan=2)
gender_label.grid(row=4, column=1)
male.grid(row=4, column=2, sticky="nsew")
female.grid(row=4, column=3, sticky="nsew")
root.mainloop()
See on effbot.org: The Tkinter Grid Geometry Manager

Tkinter returning a variable to main

Hi I have a program that runs the following way. When a user enters a number between 1-10 and hits the GO button 3 checboxes appear Left, Middle and Right. Upon the selection of only 1 checkbox a button Next appears. I disable the other ones after 1 is selected. I would like to return to the main program which checkbox was selected. How do I do this. I can do it through the Next button or through the checkbox selection. My code is below
import Tkinter as Tk
import ctypes
def setup_fc_error_message():
lines = ['fc is out of range: Please Enter a value from 1-10:']
MessageBox = ctypes.windll.user32.MessageBoxA
MessageBox(None, "\n".join(lines), 'Setup Info', 0)
def check_fc_range(fc_user):
# fc_float = si_units(fc_string_input)
# fc_float = float(fc_string_input)
fc_string_user = str(fc_user)
if (fc_user)>=1 and (fc_user<=10):
return (float(fc_user),fc_string_user)
else:
setup_fc_error_message()
return check_fc_range()
class MainWindow(Tk.Frame):
def __init__(self, parent):
Tk.Frame.__init__(self,parent)
self.parent = parent
self.parent.title('Test')
self.initialize()
def var_states_d(self):
return self.dvar
def var_states_r(self):
return self.rvar
def var_states_l(self):
return self.lvar
def cdb(self):
# print "variable is", self.dvar.get()
self.dvar_state = self.dvar.get()
# self.band_type = StringVar()
# self.band_type.set('D')
if self.dvar_state:
self.cr = Tk.Checkbutton(self.parent, text='Middle', state='disable', variable=self.rvar,command = self.crb)
self.cr.grid(row = 2, column = 1)
self.cl = Tk.Checkbutton(self.parent, text='Right', state='disable', variable=self.lvar,command = self.clb)
self.cl.grid(row = 2, column = 2)
self.nextbutton = Tk.Button(self.parent, text='NEXT', command= self.var_states_d)
self.nextbutton.grid(row=2,column=3)
else:
self.cr = Tk.Checkbutton(self.parent, text='Middle', variable=self.rvar,command = self.crb)
self.cr.grid(row = 2, column = 1)
self.cl = Tk.Checkbutton(self.parent, text='Right', variable=self.lvar,command = self.clb)
self.cl.grid(row = 2, column = 2)
self.nextbutton = Tk.Button(self.parent, text='NEXT', state='disable')
self.nextbutton.grid(row=2,column=3)
def crb(self):
# print "variable is", self.rvar.get()
self.rvar_state = self.rvar.get()
# self.band_type = StringVar()
# self.band_type.set('R')
if self.rvar_state:
self.cd = Tk.Checkbutton(self.parent, text='Left', state='disable', variable=self.dvar,command = self.cdb)
self.cd.grid(row = 2, column = 0)
self.cl = Tk.Checkbutton(self.parent, text='Right', state='disable', variable=self.lvar,command = self.clb)
self.cl.grid(row = 2, column = 2)
self.nextbutton = Tk.Button(self.parent, text='NEXT', command= self.var_states_r)
self.nextbutton.grid(row=2,column=3)
else:
self.cd = Tk.Checkbutton(self.parent, text='Left', variable=self.dvar,command = self.cdb)
self.cd.grid(row = 2, column = 0)
self.cl = Tk.Checkbutton(self.parent, text='Right', variable=self.lvar,command = self.clb)
self.cl.grid(row = 2, column = 2)
self.nextbutton = Tk.Button(self.parent, text='NEXT', state='disable')
self.nextbutton.grid(row=2,column=3)
def clb(self):
# print "variable is", self.lvar.get()
self.lvar_state = self.lvar.get()
# self.band_type = StringVar()
# self.band_type.set('L')
if self.lvar_state:
self.cd = Tk.Checkbutton(self.parent, text='Left', state='disable', variable=self.dvar,command = self.cdb)
self.cd.grid(row = 2, column = 0)
self.cr = Tk.Checkbutton(self.parent, text='Middle', state='disable', variable=self.rvar,command = self.crb)
self.cr.grid(row = 2, column = 1)
self.nextbutton = Tk.Button(self.parent, text='NEXT', command= self.var_states_l)
self.nextbutton.grid(row=2,column=3)
else:
self.cd = Tk.Checkbutton(self.parent, text='Left', variable=self.dvar,command = self.cdb)
self.cd.grid(row = 2, column = 0)
self.cr = Tk.Checkbutton(self.parent, text='Middle', variable=self.rvar,command = self.crb)
self.cr.grid(row = 2, column = 1)
self.nextbutton = Tk.Button(self.parent, text='NEXT', state='disable')
self.nextbutton.grid(row=2,column=3)
def initialize(self):
# self.frame = Tk.Frame(parent)
# self.frame.pack()
self.fc_gui = Tk.DoubleVar(self.parent)
self.fclabel1 = Tk.Label(self.parent, text = 'Please Enter a value between 1 and 10', fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Tk.Entry(self.parent, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
self.fcbutton1 = Tk.Button(self.parent, text='GO', command = self.get_fc)
self.fcbutton1.grid(row = 1, column = 1)
def add_checkbox(self):
self.dvar = Tk.IntVar()
self.cd = Tk.Checkbutton(self.parent, text='Left', variable=self.dvar,command = self.cdb)
self.cd.grid(row = 2, column = 0)
self.rvar = Tk.IntVar()
self.cr = Tk.Checkbutton(self.parent, text='Middle', variable=self.rvar,command = self.crb)
self.cr.grid(row = 2, column = 1)
self.lvar = Tk.IntVar()
self.cl = Tk.Checkbutton(self.parent, text='Right', variable=self.lvar,command = self.clb)
self.cl.grid(row = 2, column = 2)
def get_fc(self):
self.fc_user = self.fc_gui.get()
if self.fc_user:
if check_fc_range(self.fc_user):
self.add_checkbox()
return self.fc_user
######################################################GUI portion ##############################################
def main():
root = Tk.Tk()
app = MainWindow(root)
fc_gui_user = app.get_fc()
app.mainloop()
if __name__ == "__main__":
main()
I cleaned up your MainWindow class removing the cdb, crb, cld functions so you only need one for each called on_toggle to make it more efficient. You'll also notice some slight changes in the add_checkbox function using lambda to pass in the value for that specific checkbutton. And since I combined the functions I did the same for the var_states function.
I left the Tk.IntVar in there as maybe you might have needed them. Although I'm not sure what you're wanting to use them for with a Checkbutton.
As for your question, you already had a method of finding out which checkbox was selected so I'm not entirely sure what you're after, but I've outlined where you can check them.
class MainWindow(Tk.Frame):
def __init__(self, parent):
Tk.Frame.__init__(self,parent)
self.parent = parent
self.parent.title('Test')
self.initialize()
self.chk_buttons = [] # List holding each checkbutton
self.var_states = [] # List holding each Invar for checkbutton
self.clicked = False # Variable to know if a checkbutton is currently selected
def get_var_states(self, i):
# Return IntVar of clicked checkbutton
return self.var_states[i]
def on_toggle(self, pos):
# print "variable is", self.dvar.get()
self.dvar_state = self.dvar.get()
# self.band_type = StringVar()
# self.band_type.set('D')
if not self.clicked:
# Changes all except clicked checkbox to disabled
# Altering state of existing widget
for i, chk_btn in enumerate(self.chk_buttons):
if i != pos:
chk_btn.configure(state='disable')
self.nextbutton = Tk.Button(self.parent, text='NEXT', command=lambda: self.get_var_states(pos))
self.nextbutton.grid(row=2,column=3)
# You can use these if statements to do something if a certain checkbutton is clicked
# Alternately you can call self.get_var_states(pos) here, instead of adding the command
# to the Next button so it runs when a checkbutton is clicked instead of when the Next button is clicked
if pos == 0: # Left
pass
if pos == 1: # Middle
pass
if pos == 2: # Right
pass
else:
# Changes all checkbox to normal
for chk_btn in self.chk_buttons:
chk_btn.configure(state='normal')
self.nextbutton = Tk.Button(self.parent, text='NEXT', state='disable')
self.nextbutton.grid(row=2,column=3)
self.clicked = not self.clicked #Changes between True and False with each click
def initialize(self):
# self.frame = Tk.Frame(parent)
# self.frame.pack()
self.fc_gui = Tk.DoubleVar(self.parent)
self.fclabel1 = Tk.Label(self.parent, text = 'Please Enter a value between 1 and 10', fg = 'black', bg = 'yellow')
self.fclabel1.grid(row = 0, column = 0)
self.fcedit1 = Tk.Entry(self.parent, textvariable = self.fc_gui, bd = 5 )
self.fcedit1.grid(row = 1, column = 0)
self.fcbutton1 = Tk.Button(self.parent, text='GO', command = self.get_fc)
self.fcbutton1.grid(row = 1, column = 1)
def add_checkbox(self):
# Added lambda function passing in a value corresponding to the index position in the list
self.dvar = Tk.IntVar()
self.cd = Tk.Checkbutton(self.parent, text='Left', variable=self.dvar,command = lambda: self.on_toggle(0))
self.cd.grid(row = 2, column = 0)
self.rvar = Tk.IntVar()
self.cr = Tk.Checkbutton(self.parent, text='Middle', variable=self.rvar,command = lambda: self.on_toggle(1))
self.cr.grid(row = 2, column = 1)
self.lvar = Tk.IntVar()
self.cl = Tk.Checkbutton(self.parent, text='Right', variable=self.lvar,command = lambda: self.on_toggle(2))
self.cl.grid(row = 2, column = 2)
self.chk_buttons = [self.cd, self.cr, self.cl] # List of checkboxes
self.var_states = [self.dvar, self.rvar, self.lvar] # List corresponding InvVar
def get_fc(self):
self.fc_user = self.fc_gui.get()
if self.fc_user:
if check_fc_range(self.fc_user):
self.add_checkbox()
return self.fc_user

django ratings along with one to one field

models.py
class Restaurant(models.Model):
#fields here
class Food(models.Model):
rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
restaurant = models.OneToOneField(Restaurant)
class Service(models.Model):
rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
restaurant = models.OneToOneField(Restaurant)
doubt
how am i suppose to integrate the food and service along with the restaurant model and also be able to rate them aswell , please help , thanks in advance
Instead of:
class Restaurant(models.Model):
#fields here
class Food(models.Model):
rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
restaurant = models.OneToOneField(Restaurant)
class Service(models.Model):
rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
restaurant = models.OneToOneField(Restaurant)
Try:
class Restaurant(models.Model):
#fields here
food_rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
service_rating = RatingField(range=5, weight=5,can_change_vote = True,allow_delete = True,allow_anonymous = True)
KISS