UITableView Section Index not working as expected - iphone

When I add a section index consisting of "A", "B", ..., "Z" to my UITableView, everything works fine in the iPhone simulator. In this case, I get A, B, C,..., Z displayed in a horizontal line on the right hand side of my UITableview. If I add a 27th element (e.g. "Other") to the section index titles, the section index will now show A,* ,C ,* ,E,* ,H ,* ,J ,* ,L ,* ,N ,* ,P ,* ,R ,* ,U ,* ,W ,* ,Y ,Other ,* ,Other. Here * represents a circle that is rendered.
Any ideas as to why A,B,C,...,Z,Other is not displayed as I would expect?
Is there a maximum number of entries you can have in a section index?
If I've exceeded the maximum number of entries in the section index and the list gets compressed, why does "Other" show up twice in the compressed section index?
I get the following behavior when I press entries in the section index:
Press 1st Other: Title = Y, Index = 24 returned
Press last * : Title = Z, Index = 25 returned
Press 2nd other : Title = Other, Index = 26 returned

Is there a maximum number of entries you can have in a section index?
Correct. Once you move beyond a certain number of entries in the index, the OS will automatically start condensing the list (and replacing with circles) so that you can see as much of the list as possible without requiring the user to scroll. The first time I saw this I was surprised, but it does make sense ... otherwise, the OS would need to resize the elements in the index, or force the end of the index off-screen, neither of which are usable solutions.
Hope this helps. Andrew

Related

Unmerge and Assign Values Only Vertically or Horizontally Openpyxl

Using the answer provided by aka863 here: How to split merged Excel cells with Python?
I can unmerge, fill values and copy the styling. My questions is how to make the value assigning/filling process configurable.
I want the user to be able to choose whether the values will be filled vertically/horizontally.
I have tried changing the last loop where we assign the top_left_cell_values to unmerged cells. However I couldn't find a way to make it horizontal/vertical configurable. (I'm planning to use radio buttons and tkinter for this)
Its certainly possible to have the code de-merge cells and fill cells in whichever direction, vertically or horizontally regardless of which way the merge was originally. Or not fill at all, so only the top left cell retains the 'value' of the previously merged cells, which is default on unmerge.
Changing the direction of the fill requires some change and re-calculation on the max row and column values in the iter_rows loop, but is simple enough.
However it seems in your last comment you just want to give the user the option to fill or not fill on horizontal merges. In that case you just need to ask the question, and then run the iter_rows loop only if the response is yes.
The code sample below is based on the answer referenced question.
I'm assuming only single line horizontal merges since you dont mention what if anything should be done with vertical merges in the comment.
The code does initially check and indicate the merge direction either vertically or horizontally so it can be included take some action if a merge is vertical.
On code run after displaying the range and direction of the merge, the question is asked to fill, yes or no. If yes the cells are de-merged and all cells filled with the top left cell value using the iter_rows loop. If answer no then the cells are just de-merged.
from openpyxl import load_workbook
from openpyxl.utils.cell import range_boundaries
wb = load_workbook(filename='foo.xlsx')
st = wb['Sheet1']
mcr_coord_list = [mcr.coord for mcr in st.merged_cells.ranges]
direction_dict = {'v': 'vertical', 'h': 'horizontal'}
for mcr in mcr_coord_list:
print('---------------------------------------------------\n')
merge_direction = ''
min_col, min_row, max_col, max_row = range_boundaries(mcr)
top_left_cell_value = st.cell(row=min_row, column=min_col).value
if min_col == max_col:
merge_direction = 'v'
elif min_row == max_row:
merge_direction = 'h'
print(f"The cell range {mcr} is merged {direction_dict[merge_direction]}ly with the data '{top_left_cell_value}'")
while True:
demerge_fill = input('Do you want the de-merge to fill all cells(y|n)? ')
if demerge_fill.lower() in ["y", "n"]:
break
else:
print('Invalid response')
st.unmerge_cells(mcr)
if demerge_fill == 'y':
for row in st.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
for cell in row:
cell.value = top_left_cell_value
else:
print(f"Only the top left cell {mcr.split(':')[0]} will contain the data!")
wb.save('merged_tmp.xlsx')

Postgres / postgis - ensure all polygons are closed

I am needing to write a query which finds any unclosed polygons and closes them by copying the first point and creating an additional end point.
I am able to select the invalid rows:
SELECT delivery_zone_id, polygon from delivery_zone WHERE ST_IsClosed(polygon::geometry) = FALSE;
And I am able to dump the individual points from each of the polygons:
SELECT delivery_zone_id, ST_AsText((dp).geom) FROM
(SELECT delivery_zone_id, ST_DumpPoints(polygon::geometry) AS dp
FROM delivery_zone
WHERE ST_IsClosed(polygon::geometry) = FALSE
) AS coords;
And the result looks like this:
1 POINT(-96.80037 33.09812) ## Copy this point and add it to the set
1 POINT(-96.80427 33.0956)
1 POINT(-96.80401 33.09219)
1 POINT(-96.79603 33.09222)
1 POINT(-96.79346 33.09647)
1 POINT(-96.80037 33.09857)
4 POINT(-96.80037 33.099) ## Copy this point and add it to the set
4 POINT(-96.80427 33.0956)
4 POINT(-96.80401 33.09219)
4 POINT(-96.79603 33.09222)
4 POINT(-96.79346 33.09647)
4 POINT(-96.80037 33.09923)
This is where my sql skills are lacking. I need some help copying the first point and creating a new end point with that data. Pseudo queries are welcome - I just need to see what it might look like and I can fill in the gaps.
Update: Final solution
Thanks to the answer from JGH below, I was able to create the following update query. This will find any unclosed polygons and add a new end point by copying the first point.
Note: this will only work with simple "single" polygons. If you have complex outer and inner polygons, you will need to make some drastic changes to this query.
UPDATE delivery_zone dz
SET polygon=ST_MakePolygon(ST_AddPoint(subquery.openline, ST_PointN(subquery.openline, 1), -1))
FROM (
SELECT delivery_zone_id, ST_ExteriorRing(polygon::geometry) AS openline
FROM delivery_zone WHERE ST_IsClosed(polygon::geometry) = FALSE
) AS subquery
WHERE dz.delivery_zone_id = subquery.delivery_zone_id;
You can try using lines to add the point, then converting to polygon.
Let's note that creating a not-closed polygon is not possible... not too sure how you got one, and hopefully you would be able to convert them to a line at first.
So, the idea is to get the line, then add a point to it at the last position (-1). This point would be the same as the first point of this line (position 1). At last you can convert to a polygon
WITH src AS (
SELECT ST_GeomFromText('LINESTRING(0 0, 0 1, 1 1, 1 0)') As openline)
SELECT st_asText(openline),
st_asText(ST_MakePolygon(st_addPoint(openline,st_PointN(openline,1),-1)))
FROM src;
st_astext | st_astext
-----------------------------+--------------------------------
LINESTRING(0 0,0 1,1 1,1 0) | POLYGON((0 0,0 1,1 1,1 0,0 0))
(1 row)

How to change background color for each two rows in SSRS in a group

How can I write the expression in order to change background color for each two rows in SSRS?
I need something like that:
I tried expression
=IIF(Fields!Type.Value="2016 Submitted" , "LightBlue",
IIF(Fields!Type.Value="2015 Submitted" , "LightBlue",
Nothing))
But because some months dont have values it looks like this:
If I try this expression I get below:
=IIF(RunningValue(Fields!Count.Value, CountDistinct, Nothing) MOD 2 = 1, "White", "PaleTurquoise")
Dance-Henry I tried your code
=IIF(RowNumber(Nothing) Mod 4 = 1 or RowNumber(Nothing) Mod 4 = 2, "Aqua","White")
and this is what i got:
You can select the row in design pane and press F4 to setup property BackgroundColor as =IIF(RowNumber(Nothing) Mod 4 = 1 or RowNumber(Nothing) Mod 4 = 2, "Aqua","White")
Captures are attached. Do it accordingly.
RESULT is something like this
After going thru the link https://blogs.msdn.microsoft.com/chrishays/2004/08/30/green-bar-matrix/
Tested and it works well for the Green Bar Effect for Matrix. I will show it step by step here as for later reference.
Step 1: Create the Matrix and add one more column under the innermost row grouping in your matrix. (ColorNameTextbox here)
Step 2: Select the textbox of ColorNameTextbox and press F4 to setup BackgroundColor property as =Value shown below.
Step 3: Select the textbox of Matrix cell and press F4 to setup BackgroundColor property as =ReportItems!ColorNameTextbox.Value shown below.
Step 4: Drag the inner grouping header (ColorNameTextbox) to be as narrow as possible.
Step 5: Preview Pane to check the result.
If you could add a hidden color_group column and populate it with a new number at each point you want to change the color (in your case 1,1,2,2,3,3,4,4) then you could use something like the following (which works for varying size groups):
IIF(RunningValue(Fields!color_group.Value, CountDistinct, Nothing) MOD 2 = 1, "White", "PaleTurquoise")
I had a similar problem where I could not come up with alternating rows because my data has Column Groups that were the RowNumber(Nothing) method to fail. Learning from all the other posts here this is how I resolved it in steps.
I added the following code into the report properties, that provides a function to get the row number, each time it is called. The function increments the row count each time it is called. >>Right click space around the report >> Properties >> Code. Alternatively go to Code Properties Window, when the report is selected.
Add the following lines:
Public Row_Sum As Decimal = 0
Public Function Lookup_Sum( ) As integer
Row_Sum = Row_Sum + 1
Return Row_Sum
End Function
I added a new column at the beginning of the rows called No. that would calculate and show the row number.Right click the first column >>Insert Column>>Inside Group-Left.
On the expression for the new report add this line of code. Also take a note of the name of the TextBox that will have the No. Value. It will be needed in the next step. In my case the TextBox is called TextBox6 (Properties Window). >>Right Click Cell>>Expression.
Add the code:
=Code.Lookup_Sum()
I highlighted the entire row and went to the Background property and added the following expression to compute the row number.
Add the code(TextBox6 is the name Textbox name noted above):
=IIF(VAL(ReportItems!Textbox6.Value) MOD 2, "LIGHTBLUE", "WHITE")

How to find LINESTRINGs that touch in a begin/ending node

In PostGIS you can intersect two geometries using:
geometry ST_Intersection (geometry geomA, geometry geomB);
In my case both geomA and geomB are LINESTRING so ST_Intersection() returns a POINT geometry.
I want to know if the intersection occurs in a begin/end node (the geometries touch) or in the middle (the geometries intersect).
I can compare the (Point.X, Point.Y) with each ending node:
geomA.nodes(0) - geomA.nodes(len-1)
geomB.nodes(0) - geomB.nodes(len-1)
But is very complex. And I would like a simple solution.
There are 3 intersect cases.
Example 1: Two lines in a "L" shape intersect in an end node on both lines on the bottom left.
Example 2: Two lines in a "T" shape where the vertical line intersects in the middle of the horizontal line. In this case the vertical line end node touches a non-end node of the horizontal line.
Example 3: Two lines in a "X" shape. Intersection point isn't an end node for either line.
For my problem I'm only interested in finding the touching scenario like Example 2.
NOTE
This is the pseudo code I use now.
geomM, geomN Linestring
a, b, c, d, z Points.
(a,b) begin/end node for geomM ST_StartPoint(geom) and ST_EndPoint(geom)
(c,d) begin/end node for geomN
z = ST_Intersect(geomM, geomN)
SELECT geomM, geomN, z
FROM Table
WHERE
(A and not ( B or C or D))
OR (B and not ( A or C or D))
OR (C and not ( A or B or D))
OR (D and not ( A or B or C))
A, B, C, D replace ( a=z ) ( b=z ) ( c=z ) ( d=z )
This mean one node {a,b,c,d} is equal to intersection z. But only one
This return all "T" shape intersections.
You need the PostGIS function ST_Touches() here. The function returns true if the geometries touch on their boundaries, but false if they intersect. In terms of your examples, Example 1 and 2 return true, Example 3 returns false.
Relaxed solution
To select the IDs of all pairs of touching geometry(LINESTRING, xxx) records from a single table use this:
SELECT x.id AS idA, y.id AS idB
FROM my_table x
JOIN my_table y ON ST_Touches(y.the_geom, x.the_geom)
WHERE x.id < y.id;
(The WHERE clause avoids duplicate results like (132, 254) and (254, 132).)
Note that the linestrings can also touch on any of their non-node vertices. If you want to strictly follow Example 2 then you have to compare every point on every linestring against every point on all other linestrings, which is obviously going to be a very intensive operation. Example 2 is basically only feasible when you know that the linestrings are very short, preferably just straight lines.
Strict solution, straight lines only
If all LINESTRINGs are straight, i.e. composed of a starting and an ending node only, then this is your solution:
SELECT h.id AS touched, v.id AS touching, ST_Intersection(h.the_geom, v.the_geom) AS touch_point
FROM my_table h -- "horizontal" T bar, being touched
JOIN my_table v ON -- "vertical" T bar, touching
(
-- The "vertical" start node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_StartPoint(v.the_geom))
) OR (
-- The "vertical" end node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_EndPoint(v.the_geom))
);
All the requirements are checked in the JOIN ON clause. This will also return the location where the "vertical" bar of the T touches the "horizontal" bar. Note that the conditions are short-circuited when being evaluated and repeated calls to a function with the same input data are optimized to a single call.

How to align a label versus its content?

I have a label (e.g. "A list of stuff") and some content (e.g. an actual list). When I add all of this to a PDF, I get:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing
I want to change this so that the content is aligned like this:
A list of stuff: test A, test B, coconut, coconut, watermelons, apple, oranges, many more
fruites, carshow, monstertrucks thing, everything is startting on the
same point in the line now
In other words: I want the content to be aligned so that it every line starts at the same X position, no matter how many items are added to the list.
There are many different ways to achieve what you want: Take a look at the following screen shot:
This PDF was created using the IndentationOptions example.
In the first option, we use a List with the label ("A list of stuff: ") as the list symbol:
List list = new List();
list.setListSymbol(new Chunk(LABEL));
list.add(CONTENT);
document.add(list);
document.add(Chunk.NEWLINE);
In the second option, we use a paragraph of which we use the width of the LABEL as indentation, but we change the indentation of the first line to compensate for that indentation.
BaseFont bf = BaseFont.createFont();
Paragraph p = new Paragraph(LABEL + CONTENT, new Font(bf, 12));
float indentation = bf.getWidthPoint(LABEL, 12);
p.setIndentationLeft(indentation);
p.setFirstLineIndent(-indentation);
document.add(p);
document.add(Chunk.NEWLINE);
In the third option, we use a table with columns for which we define an absolute width. We use the previously calculated width for the first column, but we add 4, because the default padding (left and right) of a cell equals 2. (Obviously, you can change this padding.)
PdfPTable table = new PdfPTable(2);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.setTotalWidth(new float[]{indentation + 4, 519 - indentation});
table.setLockedWidth(true);
table.addCell(LABEL);
table.addCell(CONTENT);
document.add(table);
There may be other ways to achieve the same result, and you can always tweak the above options. It's up to you to decide which option fits best in your case.