Applescript + InDesign Selecting Body Rows In Table - excel

I am currently trying to automate some data formatting. The source data is formatted in Excel. The inDesign template is already formatted. I can right click the table and select body rows then paste the data and it looks beautiful. I am looking to remove this step but am unable to figure out how to get applescript to select the table and body rows of the inDesign template.
Neither of the following seem to work.
set selection to body rows of table 1 of active document
select body rows of table 1 of active document
Any help on this would be great.

Unfortunately the select command only works for a single row, and not all of the rows in a selected table.
Essentially, you must go row by and decide the row type. Once you've decided the row is a body row, you can select it.
The syntax for adding a selected row to another selected row is super tricky, especially without an example. See the complete script below.
tell application "Adobe InDesign CC 2015"
set allBodyRows to every row of every table of every story of active document whose row type is body row
set bodyRow to {}
repeat with i from 1 to (count allBodyRows)
set bodyRow to item i of allBodyRows
if i = 1 then
select bodyRow
else
select bodyRow existing selection add to
end if
end repeat
end tell

I think you need to reference your table differently. Try this:
set allTables to every table of every story of active document
set myTable to item 1 of allTables
Then you should be able to select rows:
tell table myTable
select first row
end tell

--author by RyuAutodidacte
tell application "Adobe InDesign 2020"
tell active document
--When the selection is a text frame
set FirstBodyCell to index of first cell of table 1 of selection whose row type is body row
set LastBodyCell to index of last cell of table 1 of selection whose row type is body row
select cells FirstBodyCell thru LastBodyCell of table 1 of selection
end tell
end tell

Related

How to automatically move an entire row when one cell moves on another sheet

I have two Excel spreadsheets. On the first sheet is a list of people's names with other data in the rest of the columns. In the second sheet, the first column is linked to the names in the first sheet (using "='Sheet1'!B1", etc); however, the rest of the columns in the second sheet are different types of data from the first sheet. If I want to move a name on the first sheet, this would automatically move the same name on the second sheet, but it won't bring the rest of the data with it. Is there a way to do this so that data follow the name?
I doubt there is an "canonical answer" because the "problem" is not canonical for Excel. In other words: Excel, which is a spreadsheet application, is not made to solve such problems.
Your assumption "the first column is linked to the names in the first sheet (using "='Sheet1'!B1", etc); " is wrong. The formula ='Sheet1'!B1 does not link to names. The formula result is what value is in 'Sheet1'!B1. If that value changes, the formula result also changes. That is exactly what you observe and call a "problem".
Linked tables are typical for a relational database system. There one table may have foreign keys to link to another table. See Foreign key. But Excel is not a relational database system.
There is Power Query to create a data query from Excel Tables which also is able to have foreign key relations between tables. But this is not really straightforward. So let's have a very simple example:
First create a workbook having two sheets having a data table each.
Example
Data of Sheet1:
Name Mail Value1
Name1 name1#example.com 123
Name2 name2#example.com 234
Name3 name3#example.com 234
Name of the Table is Data1
Data of Sheet2:
Name Value2
Name2 2345
Name1 1234
Name of the Table is Data2
Now create a Power Query from Table Data1. See Import from an Excel Table
Select a cell in Table Data1 (is on Sheet1).
Select Data > Get & Transform Data > From Table/Range.
Excel opens the Power Query Editor with your data displayed in a
preview pane.
To return the transformed data to Excel, select Home > Close & Load.
You get an additional sheet having the result of that data query. For me that sheet gets named "Data1".
Now do the same with Table Data2.
Select a cell in Table Data2 (is on Sheet2).
Select Data > Get & Transform Data > From Table/Range.
Excel opens the Power Query Editor with your data displayed in a
preview pane.
To return the transformed data to Excel, select Home > Close & Load.
You get an additional sheet having the result of that data query. For me that sheet gets named "Data2".
Now select the sheet "Data1" (The sheet which holds the first query result) and edit the query. See Create, load, or edit a query in Excel (Power Query) - > Edit a query from a worksheet -> To edit a query, locate one previously loaded from the Power Query Editor, select a cell in the data, and then select Query > Edit.
Now merge queries from Data1 with the one from Data2. See Merge queries (Power Query) -> Perform aMerge operation.
Select Home > Merge Queries.
The Merge dialog box appears.
Select the primary table from the first drop-down list, and then
select a join column by selecting the column header. This is column
"Name" in our case.
Select the related table from the next drop-down list, and then
select a matching column by selecting the column header. This is
table "Data2" and column "Name" in our case.
Select OK.
The result should be an new column "Data2" added to the query "Data1".
Now select the handle at right side of column name "Data2" and mark only "Value2" selected. The coulmn name should change to "Data2.Value2"
To return the transformed data to Excel, select Home > Close & Load.
Result should be the data table on sheet "Data1" cahnged to show the Value2 of Data2 too.
From now on all changes in Table "Data1" on Sheet1 and in Table "Data2" on Sheet2 will be put together on query result on Sheet "Data1" when you refresh that query.
Disclaimer: This answer is for the linked example in Automatically move an entire row of reference cell when one cell is moved or manipulated.
In Google Sheets, you can use the =QUERY() function to automatically move an entire row when one cell on another sheet changes.
Here is an example of how you can use the =QUERY() function to move an entire row from one sheet to another when a specific cell changes:
In the sheet where you want to move the row, create a new column and name it "Status."
In the sheet where the cell that will trigger the move is located, create a new column and name it "Move."
In the "Move" column, use an IF() statement to check if the cell you want to trigger the move is true or false.
For example: =IF(A1=TRUE,"Move","Stay")
In the sheet where you want to move the row, use the =QUERY() function to select the rows where "Move" is "Move" and "Status" is not "Moved".
For example: =QUERY(Sheet1!A1:Z,"select * where Move = 'Move' and Status != 'Moved'")
In the sheet where the cell that will trigger the move is located, use the =IF() statement to change the value of the "Status" column to "Moved" when "Move" is "Move".
For example: =IF(Move="Move","Moved",Status)
Use a script to automatically run the query and update the status every time the cell that triggers the move is changed.
Please note that this is an example and you will need to modify the formulas and sheet names to match your specific use case.
hope this helps
As the question is not really clear about this, there would be another approach if you have the following structure:
Given following data in Sheet1:
ID Name Mail Value1 Value2
1 Name1 Name1#example.com 123 1234
2 Name2 Name2#example.com 234 2345
3 Name3 Name3#example.com 345 3456
Now Sheet2 shall only pull different data from Sheet1 dependent on Name. Then Sheet2 could have following formulas filled downwards from row 2:
A2: =Sheet1!B2
B2:C4: =VLOOKUP($A2,Sheet1!$B$1:$E$998,MATCH(Sheet2!B$1,Sheet1!$B$1:$AAA$1,0),FALSE)
Now you can change data in Sheet1 and Sheet2 will always show the correct data for name because of the formulas.

Column total value at the end of a dynamic table using VBA Code

strong textSample table
I want to get the total of the columns "Value" & "Quantity" which is in a dynamic table (in which number of rows will be different each time) at the end of the last row.
If you select a cell in your table the Table Design menu will appear on the Ribbon. In it is a checkbox for Total Row. Check it.
This will add a total row to your table. In my test it contained a total only for the last column on the left. However, you can use that same formula, modified for the appropriate column name, in other columns as well. The row will automatically stay at the bottom of the table when you add rows.
To add rows at the bottom manually, place the cursor in the last cell on the right (not in the totals row but above it) and hit Tab. You can also select any cell in the table and click Insert Table Row either above or below the clicked cell.
All of the above works for a true table. You exhibit doesn't look like a true table. If it isn't, please consider one of two options. Either replace the table you already have with what is called a "Table" in Excel and enjoy the advantages that offers, or modify your question to clarify that your question applies to a list of data which are not in a table.
you could try this:
dim TotalValue as Long
dim i, value as integer
value = 1 'use the column number of Value
i = 1
Do until isempty(workbooks("yourworkbook.xlsm").worksheets(1).cells(i,Value)) = True
Totalvalue = TotalValue + workbooks(yourworkbook.xlsm).worksheets(1).cells(i,Value)
i = i + 1
Loop
i = i + 1
(workbooks(yourworkbook.xlsm).worksheets(1).cells(i,Value).value = TotalValue
Then do the same with Quantity column

When a row is added to one sheet, automatically add a row to another sheet

For Example: If I add a row between rows 1 & 2 in Excel sheet 1 then how can I reflect this change automatically in sheet 2?
Sheet 1
Sheet 2
You can use VLOOKUP function for that. First column of your Spreadsheet 2 will show first column of Spreadsheet 1 , same for the 2nd column
This is your first sheet you can change content of A and B column however you want.
For the Second Sheet add following functions
Column A - =IFERROR(VLOOKUP(Sheet1!$A$1:$A$1000, Sheet1!$A$1:$B$1000, 1, false), "")
Column B - =IFERROR(VLOOKUP(Sheet1!$A$1:$A$1000, Sheet1!$A$1:$B$1000, 2, false), "")
Now all changes from Sheet 1 will be shown in Sheet 2
On a worksheet, make a list of your names and convert the list to a table by highlighting the header and the values, press CTRL+T, give your table a name. While you still have a cell in the table selected...
On the ribbon, select Data > Get & Transform > From Table
The Power Query editor will launch in a new window and you will see the table displayed. You now have a query table. Change the name of the query. When you change the name of the query in the query settings panel on the right, it will update the name of the query in the query navigation panel on the left.
Add an index column. Go to Add Column > Index Column > From 1.
Now you have a dynamic index column attached to the names column. Go to File > Close and Load To
The query editor window will close and the Load To dialogue box will be displayed. Select Table > New Worksheet, Load to Data Model > Load.
Your query table will now be displayed on a new worksheet in your workbook. You can change the formatting on the Design tab of the ribbon.
Now, any changes you make to the original table are synced, all you have to do is refresh (Data > Refresh, from the ribbon or by right-clicking on the query table).
Try it out. Add a new name to the bottom of the data table, then go to the query table, right-click > data > refresh.

Excel Listobject table ListRows.count vs range.rows.count

I am working with listobjects in Excel and I have the following problem:
I add data to a table everytime a code is run.
Previously I have to delete all the old data.
ThisWorkbook.Sheets("comm").ListObjects(1).DataBodyRange.Delete
What happend afterwards is that I get an error with:
myNrofRowsinCOMM = COMMtbl.DataBodyRange.Rows.Count
I had a look to this post at no avail. I still dont understand what is going on.
I tried the follwoing as well:
MsgBox "COMMtbl.Range.Rows.Count:" & COMMtbl.Range.Rows.Count
MsgBox "COMMtbl.ListRows.Count:" & COMMtbl.ListRows.Count
MsgBox "COMMtbl.databodyRange.Rows.Count:" & COMMtbl.DataBodyRange.Rows.Count
If COMMtbl.Range.Rows.Count = 1 Then
COMMtbl.ListRows.Add (1)
End If
If the table is empty (row headers and an empty first row) the first line gives 2. So the range has 2 rows which seems according to reality.
COMMtbl.Range.Rows.Count=2
the sencond one gives 0. Which I dont understand at all.
COMMtbl.ListRows.Count=0
And the third one gives an error
"Object variable or withblcok variable not set"
I am trying to add rows to the table and fill them with data, for that I add a row and populate it. I want to add a row at the end, therefore I need everytime to count the number of rows. ALL fine except for the firts one when I previously deleted the whole content of the table which looks like:
Any help is welcome
Thanks a lot.
I needed a refresher, so this might help you too:
.
.Range - Includes the Header, Insert Row and Totals Row (if visible)
.DataBodyRange
- Contains the data area, between the Header Row and the Insert Row
- If the ListObject doesn't have a DataBodyRange, this property returns Null
.ListRows
- Represents all the rows of data (doesn't include Header, Total, or Insert rows)
- To delete any items from this collection, do not use the Delete method of the item
Use the Delete method of the range of the item to delete the item
For example ListRows.Item(1).Range.Delete()
.
When you do DataBodyRange.Delete the table doesn’t have the DataBodyRange object anymore, so to confirm that there are no rows with data in the table, replace
myNrofRowsinCOMM = COMMtbl.DataBodyRange.Rows.Count
with
myNrofRowsinCOMM = COMMtbl.ListRows.Count
More details from MSDN - ListObject
If you don't have data in the ListObject.DataBodyRange Is Nothing, so you can't count rows. You can get the last row of the ListObject by using n = ListObject.Range.Rows.Count and then ListObject.ListRows(n).Range
I don't know how the data you have at hand looks like, but for the sake of the example, if all you had was one column and one row, you could add the data to the last row without worrying if the table is empty or not and then using the .Add method in your example.
Dim current_n_rows As Integer
With ThisWorkbook.Sheets("comm").ListObjects(1)
.DataBodyRange.Delete
current_n_rows = .ListRows.Count
.ListRows(current_n_rows).Range.Value = NewData
.ListRows.Add
End With
You can wrap this statement around the loops you would need to fill the table.
Hope it helps! Cheers!

Open default excel data form for specific table with macro

Im working on a speadsheet with multiple large tables whose info is entered via spreadsheet based userforms i have created, as i am not familiar or comfortable using vba userforms, and i am trying to call entries back up in order to edit them.
The easiest way i can think of to do this is to open the default excel dataform. What i need to know is; is there any way to open this dataform for a specific table with criteria already entered?
eg. I need to edit a product table, so i already know that im editing the product table and i know the name for the product. I have a little userform, again spreadsheet based, where i select the entry type(in this case a product) and then enter the product name. What i want to do is use that info to open a dataform for the product table with the criteria field of the name already filled out so as to reduce time spent searching for the entry as these tables have hundreds of entries.
For this simple example I take your Worksheet with the products is called "Products". There are two columns with Names in column A and IDs in column B
On the Userform I place two textboxes called
TextBox_Productname
TextBox_ProductID
I then added the following code to the Userform that will trigger whenever the value of the productname textbox changes and it looses focus.
Private Sub TextBox_Productname_Change()
' Clear the content of all Textboxes but the Productname
TextBox_ProductID.Value = ""
' Analyse the Cells in the Worksheet called "Products"
With Worksheets("Products")
' Assume in the first row are the headers so start
' looking at the second row and go to the final one
For i = 2 To .UsedRange.Rows.Count
' check whether the value in the first column
' matches the value of the Textbox_Productname
If .Cells(i, 1) = TextBox_Productname.Value Then
' If there is a match copy the values of all
' the other columns to the textboxes
TextBox_ProductID.Value = .Cells(i, 2)
End If
Next i
End With
End Sub

Resources