Openpyxl autosize column size - size

Morning,
I would like that when cells are added, they adjust to the width of the text, any ideas?
def excel():# Writing on a EXCEL FILE
filename = (f"{myPath}/{day}.{month}.{year}.xlsx")
try:
wb = load_workbook(filename)
ws = wb.worksheets[0] # select first worksheet
except FileNotFoundError:
headers_row = ['Name','Pers. Nummer','Kürse','Funktion','Dienstbeginn','Dienstende','Schitdauer','Bezahlte Zeit','Kommentar']
wb = Workbook()
ws = wb.active
ws.append(headers_row)
wb.save(filename)
ws.append([userfinder,tagesinfo,emptycell,emptycell,emptycell,emptycell,emptycell,emptycell])
for cols in ws.iter_cols( ):
if cols[-1].value:
cols[-1].fill=(PatternFill(fgColor="D5D5D5", fill_type='solid'))
cols[-1].border = Border(left=Side(style='thin'),right=Side(style='thin'),top=Side(style='thin'),bottom=Side(style='thin'))
wb.save(filename)
wb.close()
print(f'{userfinder}-{ivunumber} - {tagesinfo} OK')
excel()

You can use python to resize column width and row height to specific values just by adding lines
ws.column_dimensions['A'].width = 30
ws.row_dimensions[1].height = 20
The above would resize column A to 30 and row 1 height to 20.
There is no auto sizing so you have to figure out the values based on the font sixe and text length of whichever cell is largest (or is to be the determining width).
If your using the headers and these never change then you should be able to determine this easily however if the text may change then you may need to calc text length and determine a formula based on that and font size.
There are discussions and examples in other questions that should help, for starters look at.
Python - Automatically adjust width of an excel file's columns

Related

Move image without copy/paste

Right now I have a Word macro that moves an image in front of specific text by copying and pasting it to that location. This works pretty well, but it is costly. If I have 1,000s of images in my word doc it could take 30 minutes to run the macro.
There has to be a better way right?
Can I move the image anchor without copy/pasting the entire image?
My end goal is to take text + an image that is aligned in a table (text left, image right), break it out of the table, but maintain that left/right nature.
Specifically, I am looking for images in tables (row 1 column 2) and want to move them to the beginning of the text in that same table (1st column, 1st row). Here is a snippet:
For Each shape In innerTable.Cell(1, 2).Range.InlineShapes
If shape.Type = wdInlineShapePicture Then
shape.Select
Selection.Cut
innerTable.Range.Paragraphs(1).Range.Characters(1).Paste
'Do it only for the 1st image found:
Exit For
End If
Next
Note, I am leaving out some safety checks for simplicity sake (this assumes I already have found a table of valid size, etc.
It is only possible to move a Shape if the target is on the same page. In that case, a Shape can be moved by changing its Top and Left properties. Unfortunately (extremely), there is no way to move an image by changing the anchor point. So the only way to move an image to another page (or story) is using copy/paste.
If an InlineShape is to be moved, just assign InlineShape.Range.FormattedText to the target Range. Or, extend a range with text to also include the InlineShape. As far as Word is concerned, an InlineShape is a character.
To achieve the stated end goal
take text + an image that is aligned in a table (text left, image
right), break it out of the table, but maintain that left/right nature
use a table with an additional column, on the right. Put the image in it as an InlineShape. Then the entire row can be handled, for example as follows.
This creates a new row in the desired position, copies the Range.FormattedText of the row to be moved to the new row. Removes the additional row this creates and also deletes the original row.
Sub MoveRow()
Dim tbl As Word.Table
Dim rwToMove As Word.Row
Dim rwTarget As Word.Row
Dim rwBeforeTarget As Word.Row
Dim posNewRow As Long
posNewRow = 1
Set rwToMove = Selection.Rows(1)
Set tbl = rwToMove.Range.Tables(1)
Set rwBeforeTarget = tbl.Rows(posNewRow)
Set rwTarget = tbl.Range.Rows.Add(rwBeforeTarget) '(posNewRow)
rwTarget.Range.FormattedText = rwToMove.Range.FormattedText
tbl.Rows(posNewRow + 1).Delete
rwToMove.Delete
End Sub

Powerpoint VBA - Autofit columns

I'm really a beginner at vba, but I've been puzzling around how to make it work. I'm creating a powerpoint presentation with Excel vba, based on data in an excel sheet a table is created on a slide in a newly created powerpoint presentation. I've got the table formatting done, which is a real hassle, by going over each individual cell and formatting them (looping, but still)....
The only thing missing is the individual column width. Based on the input data some columns might change in width,
Because of this reason I would like to have an autofit on the columns only. The rows should remain 1 line in height. But the column width should adapt to whatever would be necessary to keep the row height on 1 line.
Dim PPTtable1 As PowerPoint.Shape
With PPTtable1
.Left = 350
.Top = 150
.Width = 758
.table.Columns(1).Width = Auto
.table.Columns(2).Width = Auto
.table.Columns(3).Width = Auto
End With
This would turn the columns in the smallest possible width by stretching the height of the cells. Basically what I need is the function of double clicking on the side border of a column, and it will automatically fit to the correct width.
EDIT:
Maybe this would be interesting and important to know the order of the code:
Table is created
Format of the individual cells (bold, italic, size, font, etc...)
Data is filled in from an excel sheet
Trying to autosize the column

Using VBA in Word 2010 to change column widths in a table

I am just getting started with VBA, using my old copy of Word 2010. I want to resize two of the columns in a three column table and format the text that is in the columns. This code was generated by Word's macro recorder:
Selection.ConvertToTable Separator:=wdSeparateByCommas, NumColumns:=3, _
NumRows:=14, AutoFitBehavior:=wdAutoFitContent
With Selection.Tables(1)
.Style = "Table Grid"
.ApplyStyleHeadingRows = True
.ApplyStyleLastRow = False
.ApplyStyleFirstColumn = True
.ApplyStyleLastColumn = False
End With
Selection.Cells.VerticalAlignment = wdCellAlignVerticalCenter
Now I want the first two columns to be 1.3 inches wide and the third column to be 5.1 inches wide. Then I want to change the formatting of the text in the third column to increase the font size. The macro recorder doesn't seem to record when I resize columns. Any suggestions as to how to edit this code?
Controlling tables is rather complicated. Word does much of it the way it sees fit, but if you use VBA you must take control. It really isn't desirable that you should make your life even more miserable by invoking the Selection object. Try and make your object the table itself, for example, like this.
Dim Tbl As Table
Set Tbl = ActiveDocument.Tables.Add(Range:=Selection.Range, _
NumRows:=14, _
NumColumns:=3, _
DefaultTableBehavior:=wdWord8TableBehavior, _
AutoFitBehavior:=wdAutoFitFixed)
' wdWord8TableBehavior = doesn't change table size to match content
The table will be inserted following the selection. You may want to collapse your selection range before running this code. But now that you have a table object you can format it to your heart's content without selecting anything. There are dozens of properties. One of them which you will want to determine is Tbl.PreferredWidth = InchesToPoints(7.7) Word will not set this property automatically to the total width of your columns.
Your table has 3 columns which you can address as Tbl.Columns(1) to 3. You can set the width for each column, like Tbl.Columns(3).Width = InchesToPoints(5.1)
Similarly, you can address each row as Tbl.Rows(1) and up. Individual cells are addressed by Row and Column numbers, for example, Tbl.Cell(1, 3) which is the 3rd cell in the first row. Avoid merging cells because that will prevent VBA from being able to count them off.
The text in a cell is contained in its range, for example, Tbl.Cell(1, 3).Range.Text. You can both read and write this property. Bear in mind that Word keeps a paragraph-end mark at the end of each cell's range. When you write to a cell Word will add it for you, even if you thought of adding it yourself. But when you read a cell's text you need to remove the last character, for example,
Dim Rng As Range
Set Rng = Tbl.Cell(1, 3).Range
With Rng
.End = .End - 1
Fun = .Text
End With
Here Fun is the variable (As String) that contains the actual text part of the cell's contents.
You can address the paragraphs within a cell as part of the range, for example, Tbl.Cell(1, 3).Range.Paragraphs(1). I always avoid having more than 1 paragraph into any cell. However, you could address more paragraphs as (2) etc. You can apply all formatting available for paragraphs to each paragraph in each cell, and all the text in each paragraph can be subjected to all the formatting Word has available for text.

Write new entry into cell and autofit column width if it needs to become wider to fit the new entry?

I write a value into a cell:
Range("A1").Value = 13/3/2015
If the column is wide enough to accommodate that entry, I don't want it to change. If it is not wide enough, I want it to autofit. What is the best way of doing this?
The following should work
Range("A1").Value = 13/3/2015
Width = Range("A1").EntireColumn.ColumnWidth
Range("A1").EntireColumn.Autofit
if Range("A1").EntireColumn.ColumnWidth < Width then Range("A1").EntireColumn.ColumnWidth = Width
But I hope that there is a more clever way that does not require me to autofit the column width needlessly.
Autofit will adjust to the longest cell width in the column, provided wordwrap is no on. It will not change it if a larger width is not found. Your extra test is redundant.

Attaching a Textbox to a point or line on a chart in Excel/VBA

I was wondering how to attach a textbox to a point or line in an Excel chart for the macro I am working on. I have been using the .AddTextbox method such as
.Shapes.AddTextbox(msoTextOrientationHorizontal, 150, 250, 100, 15) _
.TextFrame.Characters.Text = "Temperature"
But I have to then manually drag the textbox over the line on the chart it is representing as the orientation is of the chart not the line. Is there a way to convert the line/point to a chart orientation which I could use as a variable? or another way? Possibly using the datalabel function, though I want to be able to customize one of the axis locations. Thanks
To solve your question you need to get the left & top position of two objects:
chart itself, which position is set in relation to top-left corner of sheet range area
point in series which position is set in relation to top-left corner of chart
Combination of both result with the following code (fixed parameters-required changes to your situation, could be more dynamic with loop)
Sub Add_Text_to_point()
Dim tmpCHR As ChartObject
Set tmpCHR = Sheet1.ChartObjects(1) 'put index of your chartobject here
'for first serie, for point 2nd here
'(change accordingly to what you need)
With tmpCHR.Chart.SeriesCollection(1).Points(2)
Sheet1.Shapes.AddTextbox(msoTextOrientationHorizontal, _
.Left + tmpCHR.Left, _
.Top + tmpCHR.Top, _
100, 15) _
.TextFrame.Characters.Text = "Temperature"
End With
End Sub
After result presenting the picture below.
Another option would be to use the data labels of Excel. I see two more elegant options:
Make a new data series with just one entry in your chart, give the series the coordinates and the name of the label you want to see. Now activate the marker option for the series (if not done already), right-click on the data point, click "add data labels". Now you'll see the y-Value of the point. By right-clicking again and choosing "Format Data Labels" you can change the text to the series name, also the position, the border, etc. are modifiable. Below an example with two data points. You could delete the second point, the line and the marker but like this you see how it works.
Similarly to the solution from KazJaw you can use the actual data points of your series for attaching custom data labels. This requires some coding, I used this for the chart named "Topview" and wrote percentages next to the data point
Sub Add_Text_to_data_points()
percentages(1) = 0.1
percentages(2) = 0.23
'.... further entries
chartNumber = findChartNumber("Topview")
collNumber = 12 ' index of the "points" series
Set tmpCHR = ActiveSheet.ChartObjects(chartNumber)
For i = 1 To tmpCHR.Chart.SeriesCollection(collNumber).Points.count
With tmpCHR.Chart.SeriesCollection(collNumber).Points(i)
If percentages(i) <> 0 Then
.DataLabel.Text = format(percentages(i), "0%")
End If
End With
Next
End Sub