How do I insert a table into a cell using word vba or a table within a table? - vba

I am new on VBA, I am creating a script to generate a report from a DB, I have been able to assemble a general draft of my report but I need to insert a table into an existing cell inside a word document, I have been surfing around but I am unable either to do a websearch with the correct terms in order to find some guidance on how to achieve this, If I am able to do it with my mouse I am sure I am able to do it through scripting, any resources that would help me in the right direction will be deeply appreciated.

Ok I found a way, The secret is in the Range, to specify where do you want your nested table to be placed.
so, I am using Powershell so the syntax might vary a little
For creating the Table in the Document (assuming you already have a created document, if not you are missing that part which I am not going through since they already are several question/answer pairs on that subject).
$TableX = $oDoc.Tables.Add($oDoc.Bookmarks("TableX").Range, 4, 3)
So TableX is our actual table, then we are telling word to use the helper method on the oDoc (Which is the name of our document object) to add a table, with a Bookmark named TableX (I will again not do a large explanation on this one, just for practical purposes, we name the Bookmark so we can reference to the table by Bookmark name later if we need to add data to it or manipulate it in any way we need) and at the same time we are calling to the method Range which is going to tell the Document Object where do we want the table to be placed, since we have not defined the range explicitly it will insert it in the next available line on the document,
Finally we specify how many rows and columns we would like in the table.
That is what we need for creating a table, now the tricky part, how do we insert a nested table, and moreover how do we specify where do we want this second table to be nested.
Well, with this:
$oNestedTable = $oDoc.Tables.Add($TableX.Cell(4, 2).Range,7,3)
We name our nested table oNestedTable, then we are calling the same helper method we called before to add a new table to the document, but wait, look carefully at the differences, the range part of the command is pointing to a specific cell on in our first table, that is in the fourth row within the second cell, it is there where we are explicitly telling the document to insert a new table with 7 rows and 3 columns.
I hope this gives you some bare minimum guidance.
Regards
en

Related

Access 2010 Database Clenup

I have problems with my records within my database, so I have a template with about 260,000 records and for each record they have 3 identification columns to determine what time period the record is from and location: one for year, one for month, and one for region. Then the information for identifying the specific item is TagName, and Description. The Problem I am having is when someone entered data into this database they entered different description for the same device, I know this because the tag name is the same. Can I write code that will go through the data base find the items with the same tag name and use one of the descriptions to replace the ones that are different to have a more uniform database. Also some devices do not have tag names so we would want to avoid the "" Case.
Also moving forward into the future I have added more columns to the database to allow for more information to be retrieved, is there a way that I can back fill the data to older records once I know that they have the same tag name and Description once the database is cleaned up? Thanks in advance for the information it is much appreciated.
I assume that this will have to be done with VBA of some sort to modify records by looking for the first record with that description and using a variable to assign that description to all the other items with the same tag name? I just am not sure of the correct VBA syntax to go about this. I assume a similar method would be used for the backfilling process?
Your question is rather broad and multifaceted, so I'll answer key parts in steps:
The Problem I am having is when someone entered data into this
database they entered different description for the same device, I
know this because the tag name is the same.
While you could fix up those inconsistencies easily enough with a bit of SQL code, it would be better to avoid those inconsistencies being possible in the first place:
Create a new table, let's call it 'Tags', with TagName and TagDescription fields, and with TagName set as the primary key. Ensure both fields have their Required setting to True and Allow Zero Length to False.
Populate this new table with all possible tags - you can do this with a one-off 'append query' in Access jargon (INSERT INTO statement in SQL).
Delete the tag description column from the main table.
Go into the Relationships view and add a one-to-many relation between the two tables, linking the TagName field in the main table to the TagName field in the Tags table.
As required, create a query that aggregates data from the two tables.
Also some devices do not have tag names so we would want to avoid the
"" Case.
In Access, the concept of an empty string ("") is different from the concept of a true blank or 'null'. As such, it would be a good idea to replace all empty strings (if there are any) with nulls -
UPDATE MyTable SET TagName = Null WHERE TagName = '';
You can then set the TagName field's Allow Zero Length property to False in the table designer.
Also moving forward into the future I have added more columns to the
database to allow for more information to be retrieved
Think less in terms of more columns than more tables.
I assume that this will have to be done with VBA of some sort to modify records
Either VBA, SQL, or the Access query designers (which create SQL code behind the scenes). In terms of being able to crunch through data the quickest, SQL is best, though pure VBA (and in particular, using the DAO object library) can be easier to understand and follow.

Transform and load a large CSV to multiple worksheets in one Excel file

Back Story:
NEW PROJECT FROM MANAGEMENT: I have been given a soft project from my boss to evaluate one of our current ETL plans to look for room for improvement in the process, and I am looking for guidance.
MOTIVE: Excel is currently being used and crashes quite often during the process due to file size.
TASK: Every month an analyst receives a large csv file from a survey vendor containing up to 750 columns (not all unique names) with over 15,000 rows to simply transform a large csv file into an excel file with seven worksheets broken up based on the column headings in the csv. Details of how it is broken up is below.
My question is one large csv being transformed into an edited excel file with multiple worksheets any easier or quicker using VB.NET and VS2010 or VBA for that matter, or would using Excel be the simplilest way to continue this process? I am an Expert Excel user but I am still very much a beginner to intermediate at coding in VBA, VB.NET or any other language.
Detailed Question:
I am open to using free or open source software, but I am most familiar with VB.NET and Excel and Excel-VBA. I have played around a bit coding a simple windows form application to load the csv into a datatable using similar TextFieldParser code found here. I have thought of loading it into an array or even a 2d array to more easily edit the column headings and find the duplicate column headings. The datatable option still leaves me with more questions than answers because I need unique column headings and not sure if I should bother with a datatable if I'm going to just write an excel file right away. I tried CSVreader from CodeProject won't work on files with duplicate header names. I feel as though I am having writers block as I am not sure which direction I should take handle such a process. Any input you can provide will be much appreciated, and I apologize if this question does not have a single and clear best answer, Thanks.
Current Analyst tasks using excel
The current analytical plan has said analyst to open the csv in excel, insert a row above row 1 and use a vlookup to replace the 'New' column names with the 'Old' column names based on a simple two column lookup table on a separate worksheet. For example
New becomes Old
"org-name" becomes "org_name" or
"item_1_Vendor" becomes "item_1" or
"date-created_Survey" becomes "date_created"
etc...checking all sent "New" columns against the list of all possible 750 columns.
Then they paste values of the first row and then delete the 2nd row which contained the New headings we want to change.
Then the analyst has to fix the primary key on the file which is called "sid".
The Survey ID field (sid) should have a number for each row of the data file. Sometimes the sid shows up under the sid_HCAHPS or the sid_CGCAHPS fields instead.
The analyst would insert a column next to the "sid" field and put a formula in it like this, for example:
=IF(BE2<>"",BE2,IF(RD2<>"",RD2,IF(UH2<>"",UH2,"")))
Actual cell references would change but in the example excel formula,
"sid"=Range("BE2")
"sid_HCAHPS"=Range("RD2")
"sid_CGCAHPS"=Range("UH2")
Once the newly created primary key column is made and filled without blanks, we can delete the original "sid" column.
The next step is to check the columns because there may be a redundant HCAHPS section of columns (due to a second survey being sent and then returned- coded as Wave 2), delete second set of columns "sid_HCAHPS" through "language"
Next is the largest alteration because we have setup a system where we send this information to our database admins in the form of a seven worksheet excel file to be loaded by an MS Access Query that creates a table from each sheet that gets loaded into our proprietary business intelligence software. All Done!!
Is your question, "can VB.net automate our current analyst tasks?" -If so, then yes.
You could use the streamreader class to get data from your csv
(http://msdn.microsoft.com/en-us/library/system.io.streamreader.aspx)
Then store it either in an array as you mentioned or use the *list class
(http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx)
Once you've got all your data stored you'll need to automate excel, this is quite straight forward but here's a link to get you started with that as well: http://support.microsoft.com/kb/301982/en-gb
With the list class you can create a list of custom objects using either classes or structures. eg.
We define a structure:
Structure rowOfData
Public intPrimaryKey as Integer
Public strIceCreamName as String
Public decPrice as Decimal
End Structure
We can then create a rowOfData and add properties to it:
Dim iceCream1 as rowOfData
iceCream1.intPrimaryKey = 1
iceCream1.strIceCreamName = "Mr Whippy"
iceCream1.decPrice = 0.99
We create a list with:
Dim listOfIceCreams as New List(of rowOfData)
And add to it like this:
listOfIceCreams.Add(iceCream1)
listOfIceCreams.Add(iceCream2)
etc.
And access the members of the list like this:
listOfIceCreams(0).decPrice 'gives us the price of the ice Cream that was added to the list first.
There are also a lot of other useful methods that lists have which arrays don't. You could have a look through that msdn list class link to see if anything jumps out at you that you might need

Any way to make Word table first row repeat when inside other table?

I'm automating a word document in vb.net. My problem is I need a table within another table to repeat the first row. Is there any way to do this?
The table's textwrap is set to none, and the first row is the only one that has the repeat has header property set.
I CAN'T take the table out of it's containing table. This solution is not an option.
This has nothing to do with the fact that the document is automated too.
Using word 2010.
I just did a quick test with Word 2010.
I created a table, and checked "repeat as header row at the top of each page".
Sure enough, that worked.
Then I created another table, and cut/pasted the first one into it.
The header was not repeated in the Word UI, although the property remained set.
I had a quick look around for properties which might affect the behaviour of nested tables, but couldn't see any.
Then I googled "word nested table repeat header row", which returns quite a few relevant results.
Conclusion: you can't make a header row in a nested table repeat on subsequent pages. Tricks like putting it inside a content control didn't seem to work either.

Comparing two columns and matching values from seperate work sheets

The goal of my project is to create an out of office program that will allow easy tracking and auditing of our Sharepoint site as it doesnt have a built in system to do. I have no background in VBA, but I have done quite a bit of python. That being said I've ran into my first issue. I'm not sure how the syntax works, and what commands I should be using to get the results I want. I.e. sheets vs worksheet vs worksheets.
I have a workbook, 1 sheet is Raw Data, in which I import data from a sharpoint site. It displays the following columns
Resource Name -- Absence Type -- ID -- Start Time -- End Time -- Created -- Modified by
The next sheet I have is tracking, it's called Tracking. On this page the user imputs Resource Names they want to track into Column A, and then the remainign columns are going to display the number of absences that name has so it will look something like
Resource Name -- Vacation -- Sick -- WFH
Clooney, George -- 2 -- 0 -- 7
A counter will run based on each instance that appears in raw data and adds the number to the counter based on the absence type from raw data.
I need a way to loop through Raw Data and look for the names that appear in the Tracking data. If Possible I'd like to store them in a third worksheet jsut for testing purposes. I know the logic I need to use, but what I dont know is the syntax to refrence the pages together. Any insight on the best way to accomplish this?
Question : I need to Search raw data for every instance Resource Name appears in it from the Tracking page and store into another worksheet.
If you don't want to use PivotTables (can be hard to search later) this is the way to do it with COUNTIFS. This formula goes in the "Sick" column of Tracking in row 2 (assuming row 1 is headers).
=COUNTIFS('Raw Data'!A:A,Tracking!A2,'Raw Data'!B:B,"Sick")
It assumes that in Raw Data Name is in column A and AbsenceType is in Column B, but it doesn't matter how many records there are.
The way I understand your question (and it wasn't easy), you are dealing with a bunch of timesheet info. You seem to be trying to count the number of instances of different kinds of time off that people are taking - whether that be vacation, sick or working from home(WFH).
I've never heard someone's name referred to as a "Resource Name" lol.
You really don't need to use VBA for this problem - at least not anything that you can't just record a macro for - it seems to be a rather simple problem that can you solve using a pivot table.
If you want to you can set up a vlookup reference to this pivot table to create the little form that you seem to be trying to create. But really I think your better off just teaching whoever is going to be using this about pivot tables. Let me know if I misunderstood your question and I'll be happy to delete this post.

Use columns.add(...) in Word with non-uniform column widths?

Problem I'm having is that table.Columns.add(ref Object BeforeColumn) requires a reference to another column in the table. However, when I try to access the last column in the table to pass as a reference using table.Columns.Add(table.Columns[table.Columns.Count])
I get the error:
"Cannot access individual columns in this collection because the table has mixed cell widths."
As my current work around, I catch the error, and call table.Columns.DistributeWidth() to make sure the columns are uniform and run the rest of the code. However, I lose the formatting of my cell widths this way, which is unfortunate.
Is there any way I can workaround this without losing the cell width?
(I realize one way is to store every cell's width before running this process, and then re-applying the widths afterward, but this seems like a very costly solution to something that should be simpler)
I've found one way to do it. Here's how I approached it.
*Caution, I'm assuming that the table is uniform. i.e. The number of columns is the same across all the rows. (Note, the API has a Table.uniform function, but the description is not complete. In the API it says "True if all the rows in a table have the same number of columns." However, it also checks if the columns have uniform width).
Instead of using table.Columns.Add(table.Columns[table.Columns.Count]) to add a column before the last below, I select a cell in the table and used the insert command:
//assuming table is the name of the table you want to add columns to
table.Cell(1, table.Columns.Count).Select();
word.Selection selection = table.Application.ActiveWindow.Selection;
selection.InsertColumns();
This might actually be a better way to add columns, as the api gives you way more options on how to insert (i.e. use InsertColumnsRight to insert to the right of the column). The Columns.Add(...) function by default inserts to the left of the select