VB.Net Word Tables: Select specific Cells in Column - vb.net

I wrote a program that creates a table in Word which is filled with values from a database. That works fine so far.
The first column of that table shall contain categories for items in the table and those categories should be merged cells with the span of all items in that category. Basically this is working.
Here's the code
'Select the first cell of a category in column 1
wordtable.Cell(categoryPos, 1).Select()
'Move down till all cells of column 1 in rows with items of that category are selected
word.Selection.MoveDown(wordoptions.WdUnits.wdLine, (numberMachines - 1), wordoptions.WdMovementType.wdExtend)
'then I change the rotation, background-color, write text etc.
The problem is the page break. After a page break the listing looks like on this picture:
I need to know a method of selecting multiple cells without the Move-command.
If this was Excel I would do something like
ActiveSheet.Range(Cells(x1, y1), Cells(x2, y2)).Select
Selection.Merge()
But since Words range is only one-dimensional I'm kinda stuck here.
Someone got a hint?

Sometimes it's easier than expected:
Dim r As wordoptions.Range
r = doc.Range( _
Start:=wordtable.Cell(kategorypos, 1).Range.Start, _
End:=wordtable.Cell((kategorypos + numberMachines - 1), 1).Range.End)
r.Select()

Related

Select only one column even if a merged range lies below

Test case:
Take an empty sheet, and merge the range "D2:F2". You can do this manually.
Then, activate the macro recorder and select the column E by just clicking on the E letter on the top of the spreadsheet. You will get the following:
Columns("E:E").Select
Now, try to run this line of code from the same macro directly: you will see that it selects the three columns D, E and F.
Question:
Is this a bug of the macro recorder? Or, rather, a bug of VBA itself (that detects the merged range in my column and decides to extend the selection even if explicitly asked to select one single column)? How should I do to select only one of the columns on which a merged range lies via VBA code, exactly as I can do manually?
Need:
I have a spreadsheet with year on a line, months on the below line and days on the below line.
Hence, the days are just cells but months and especially years are shared/merged cells among the several days.
My need is just to detect the current day and select the column, in order for the user to see on which day they should look the data at. But, because of the "years" cell widely merged just above, the entire year is selected.
No, this is not a bug.
Why: Try to manually select the range E1 to E5. That is what is going on when you use Columns("E:E").select. Think of it as .Select not selecting the column, but instead selecting each cell from top to bottom.
The .select method isn't something you should depend on. What exactly are you trying to use select for? There is another (quite arguably better way) to do this.
Edit: Also, as my father always says, merged cells shouldn't be used. He uses "center across selection" instead, which looks exactly like a merged cell without any of the seemingly buggy behavior.
Need: I would use the macro to highlight the data... probably with something like this...
Range("E7").Interior.ColorIndex = RGB(0, 0, 0)
I feel that the question is genuine unlike some of the comments here. I will try to explain.
Using the test case from the question, say I want to do some action only on column D (say change its column width), without changing the same for columns E to F. I can do that in excel by selecting column D specifically by pressing on column header (press on that "D" in the column names bar). If we select column using range selection (mouse or keyboard shortcut CTRL+SPACE), it extends the selection to include E and F columns. But if we press that column D on the header, it only selects one column. I expect VBA to do the same.
Sadly, I couldn't find anything to "select" a single column or range which includes cells merging through multiple columns or range. However, I could do the action on that single column.
I tried following that didn't work. And I feel that it should work.
Range("D:D").Select
Didn't work. Extends the selection to include merged cells. I guess, this is okay.
Columns("D").Select
Didn't work. Extends the selection to include merged cells. I feel this is not okay.
Columns("D").EntireColumn.Select
Even this didn't work. This definitely should've.
So finally I directly applied the action without selecting the cells.
Column("D").ColumnWidth = 10
And this did it. Only the column D width was changed, leaving column E and F untouched. Similarly, I could do font change and other actions.
Only drawback is that I have to do all actions individually. So, I use a loop to perform action on the selection.
Something like this:
For Each x in Range("D:D")
x.font.size = 10
x.font.name = "Calibri"
'...and so on...
Next x
You probably know the row in which the days start. Therefore, instead of selecting the entire column, you could define a range starting from the first day row to the last day row and select that range.
REQUIREMENTS:
Your table should have this values and formats
Then you can loop through each column on row 4 -just assumed- and check each value if they match today. Next you can scroll to that cell using Application.Goto.
CODE:
Sub FindToday()
Dim wsTable As Worksheet '<~ worksheet with your table
Set wsTable = Sheet2
Dim Cols As Integer '<~ a variable to loop through columns
With wsTable
For Cols = 1 To .Cells(4, .Cells.Columns.Count).End(xlToLeft).Column + 1
If .Cells(4, Cols).Value = Date Then '<~ check if the date is today
Application.Goto wsTable.Cells(1, Cols), True '<~ scroll to that cell if true
Exit For
End If
Next
End With
End Sub
If you want just to hide the particular column if there is merged cell try not to select the column just use like this for example -- Columns("N").EntireColumn.Hidden = True... This will solve your doubt.

Copying values across a dynamic column and row range

I have the following code that:
copies the column headings (in row 1) from column C across to the second last column
pastes these column headings in row 1 in the column 2 across from the last column with data
pastes the column headings alongside each row of data through to the bottom row
Sub GLDR()
'use End(xlUp) to determine Last Row with Data, in column A of the GLDRYYPP tab
Dim lastRowDR As Long
lastRowDR = Sheets("GLDRYYPP").Range("A" & Rows.Count).End(xlUp).Row
'copy the cost type categories and paste alongside the cost centres
CTNameCol = "S2:AF" & lastRowDR
Sheets("GLDRYYPP").Range("C1", Range("C1").End(xlToRight).Offset(0, -1)).Copy
Sheets("GLDRYYPP").Paste Destination:=Sheets("GLDRYYPP").Range("C1").End(xlToRight).Offset(0, 2)
Sheets("GLDRYYPP").Range(Range("C1").End(xlToRight).Offset(0, 2), Range("C1").End(xlToRight).Offset(0, 2).End(xlToRight)).Copy
Sheets("GLDRYYPP").Paste Destination:=Sheets("GLDRYYPP").Range(CTNameCol)
End Sub
The first two steps have been set to be dynamic for any additional columns added but I am having trouble writing some code that will paste the data through to the bottom row. As you can see the range "S2:AF(last row)" has been written to make use of the result from the lastRowDR dimension.
Is there a way to write the code which will make the copy dynamic across the columns and rows?
Yes there is a way to write the code which will make the copy dynamic across the columns and rows. What you need to do is to identify a distinct quality about the cost centres so that you locate it using something like ActiveSheet.Cells.Find(Txt).
Then you'll be able to determine what CTNameCol should be. There is some helpful info here: Range.Find Method.
If you add add a picture of your spreadsheet I will update this answer with more precise information.

Dynamic calculation in Excel based on a cell value

I've got a challenge in Excel i hope you guys can solve for me.
I have a drop down list (weeks) where i select the week 2015-18 to 2016-17. (nr 1 in picture)
In the cell called LY (nr 2 in picture) I want that to type the result of a dynamic sum range, based on the weeks input.
Picture of setup of the text above
The calculation logic is:
If i select week 2015-20, the VBA or formula should sum(F5:F7)/(G5:G7).
So in other words, I want a dynamic calculation that starts from week 2015-18 (F5/G5) and then sums the values down to the value that i have selected in "Weeks"
Picture of the setup of the logic values
The value of this calculation should be shown in LY (first picture, nr 2).
I really hope you can solve this for me. I've got more rows to calculate, so if you could come up with a "global" code that works for that, it would be great
ok, so you do not need VBA for this.....
for the sake of easier updates; mark the weekrange, right click them and give them a name, with Define name
I called it yearlyweeks
The two drop downs lists, will contain the value corresponding to the text indicating that week.
So we can use this to get a cells address by value (if that text is unique in the range named yearlyweeks):
=ADDRESS(MATCH(H8,yearlyweeks, 0), 2)
where H8 is the cell address of a dropdownlist cell. 2 is the column index of the "B" column
this will result in something like:
$B$2
where the 2 indicates the relative row index, in the range, not the absolute row number.
we are really not interested in the column, or relative row, only the absolute row, but so far we can live with relative..:
=ROW(INDIRECT(ADDRESS(MATCH(H8,yearlyweeks, 0), 2)))
this will give you the relative row of the cell coresponding to what you selected on the drop downlist for one of the lists. So I would do this in two calculation cells, just to avoid the next piece getting too long..
lets let the calculation cells be in I10, and J10..
I10 hold the relative row for the beginning week
J10 for the ending week
below create a new set of cells with:
="F"&(I10 + 7)
and
="G"&(J10 + 7)
where 7 is the row offset of yearlyweeks
in yet one more cell J12 we make the range string:
=CONCATENATE(I11;":";J11)
and then does the calculation in the final cell:
=SUM(INDIRECT(J12))
Now I can do this as a one liner, but you really would hate that

Removing a row in a table if it doesn't contain keyword

Right now I have a really long table in a Word doc which I populated from an Excel worksheet. It has 6 columns and I'm trying to code something in Word VBA that will go through all the rows in the table and delete the entire row if the cell in the first column DOES NOT start with an equal sign ("=").
For example, I'm only trying to keep the rows that has texts like,
"=1+S -03F7", "=1+M -06M1", etc. etc.
How would I code this? I can't give the code anything specific to look for since the parts after the equal sign will be different for every row.
So this wouldn't work, right?:
If Not ActiveDocument.Tables(83).Columns(1).Range.Text = "=" Then
EntireRow.Select
Selection.Delete
I guess I should reference to cells in column 1, not the column itself... Also, it doesn't work because it's only looking for things with just the equal sign... And I don't know how I can get it to select the row if it find the cell without the equal sign. I don't know how to match by case in the cell of the first column.
You can loop through the rows in the table using the Rows property. You can then find the first cell in that Row using the Cells property. You can then check just the first character of the Range:
Sub DeleteUnwantedRows()
Dim t As Table
Dim r As Row
Set t = ActiveDocument.Tables(1)
For Each r In t.Rows
If r.Cells(1).Range.Characters(1) <> "=" Then r.Delete
Next r
End Sub

Auto Fill Row B with the last four characters of Row A

So basicly i want a VBA script to fill Row B with the last four characters that are in Row A
RowA contains a telephone number with around 12 numbers in it.
Assuming that you meant to say
I have a series of telephone numbers in column A. I would like to
create a second column in which I have just the last four digits of
these numbers. I am new to Excel. Could someone please help me get
started on this?"
The answer would go like this:
In Excel you can create formulas that compute "something" - often based on the contents of other cells. For your specific situation, there is a function called RIGHT(object, length) which takes two arguments:
object = a string (or a reference to a string)
length = the number of characters (starting from the right) that you want.
You can see this for yourself by typing the following in a cell:
=RIGHT("hello world", 5)
When you hit <enter>, you will see that the cell shows the value world.
You can extend this concept by using a cell reference rather than a fixed string. Imagine you have "hello world" in cell A1. Now you can put the following in cell B1:
=RIGHT(A1, 5)
and you will see the value "world" in B1.
Now here is the cool trick. Assume you have a bunch of numbers in column A (say starting at row 2, since row 1 contains some header information - the title of the column). Then you can write the following in cell B2:
=RIGHT(A2, 4)
to get the last four digits. Now select that cell, and double-click on the little box in the bottom right hand corner:
Like magic, Excel figures out "you want to do this with all the cells in this column, for as many rows as there is data in Column A. I can do that!" - and your formula will propagate to all cells in column B, with the row number adjusted (so in row 3, the formula will be
=RIGHT(A3, 4)
etc.
Try
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
With ws.Range("B2:B99")
.Formula = "=Right(A2, 4)"
.Value = .Value
End With