Simultaneous change of table cell values in tables on different pptx slides - vba

I got two (or more) same tables on two (or more) different PowerPoint slides, one table per slide.
I need to update the respective cell in all tables whenever I modify this cell on just one of them.
I have been trying to access the cell value and store it as a variable using pptx package.
The only thing I could do is InputBox() but it is not convenient.

Since PowerPoint lacks bookmarks and has only a few fields, you'll have to specify the read and write locations the long way. Keep an eye out for tables with merged or split cells, those can pose an addressing problem.
Sub UpdateTableCell()
Dim CellContent$
CellContent$ = ActivePresentation.Slides(1).Shapes(1).Table.Rows(2).Cells(2).Shape.TextFrame.TextRange.Text
ActivePresentation.Slides(2).Shapes(1).Table.Rows(3).Cells(4).Shape.TextFrame.TextRange.Text = CellContent$
End Sub
You'll probably find this more convenient to use if you add it to the Quick Access Toolbar. If the icon is in the 5th position on the QAT, you can run it with Alt + 5 for a keyboard shortcut.

Related

Change Style of ListBox

In Outlook 2010 I have a UserForm with a ListBox.
This ListBox has 4 columns where I show a list of attachments (the columns "File-Name", "File-Type", "File-Size" and "Target-Directory".
Unfortunately the ListBox is restricted in layout functionality, the user can not adjust the column width at runtime (so I have to specify the width of the columns by design).
Because the file path can be quiet long, I set the width of the last column to 999 Pt.
So my ListBox has a horizontal scrollbar.
I want to have the following layout changes to my ListBox:
Add column headers
Change the alignment of a column to right-aligned
Optional: allow the user to sort the list by any column
Optional: allow the user to sort change the width of any column
Optional: show a grid in the ListBox
For 1. I found some answers that this is very complicated and I should use static labels above the list instead.
This is not possible, because my ListBox can be scrolled horizontally.
Is the ListBox really so restricted or is #1 and #2 possible somehow?
I know that there are foreign components available, but I am not allowed to buy any component.
And my solution should work at my colleagues too, so they would also have to install these components.
I have been experimenting with possible solutions to your problem. I think I have taken the listbox approach as far as it will go so I will share what I have discovered.
I can find nothing on the web to suggest that anyone believes you can have listbox column headers without using property RowSource. To use RowSource, you set it to an Excel range.
I got Outlook to create an Excel workbook and to write some data to it. Unfortunately, I could not find any way of getting an Outlook user form to access an Excel range. The syntax for setting RowSource is:
ListBox1.RowSource = "Emails!A2:D20"
This is not the standard syntax for a range and I have failed to discover any method of extending it to include a workbook name.
Jonah_Hess describes an interesting approach in https://stackoverflow.com/a/43381634/973283. He has two list boxes. One is a one-line listbox that contains the headings and the other contains the data. The two listboxes are set to the same number of columns with the same widths. This gives an attractive appearance but if you scroll the data listbox, the headings listbox does not scroll with it. This is not really any different from placing labels above a single listbox.
I tried putting the headings and the data list boxes in a frame and scrolling the frame but could not get it to work. I have used frames with VB user forms but the functionality is very different so there are no lessons learnt that I could bring to a VBA user form. Perhaps someone more familiar with VBA frames could get this approach to work.
I gave up trying to get a solution in Outlook. An Excel macro can access Outlook data so I tried that approach.
I created a macro-enabled workbook. Within it, I have two forms both of which fill the screen to conceal the worksheet. The first form just says: “Please wait while I load data from Outlook”. I am not clear about the data on your form so I imported selected details from a folder full of junk emails which I wrote to a worksheet. I sized the columns for the list box to match those for the worksheet. The result was:
The text is a little small but I think it is readable. The listbox at the bottom allows me to select emails for different periods. Long ago I had problems with RowSource which meant I could change the values in the range but I could not change the size of the range. I have either managed to avoid that problem today or it was a bug that has been fixed.
You can see that the headings are displayed. The columns are a little wide but I consider them to be a reasonable first approximation. Options to change the widths would be easy to implement.
The changes you ask for:
Add column headers. Done
Change the alignment of a column to right-aligned. Possible but difficult. You would need to pad the text with an appropriate number of leading spaces.
Optional: allow the user to sort the list by any column. The data is in a worksheet so easy.
Optional: allow the user to change the width of any column. I have set the column widths at runtime to show it is possible.
Optional: show a grid in the ListBox. Not possible.
If the above is interesting, I could show you all my code and instruct you on creating the forms so you could duplicate my experiment. Alternately, I could just explain: how I imported the Outlook data to Excel, how I included the column headings and how I set the column widths.
I cannot find anything to suggest that anything better can be achieved with listboxes.
An alternative approach is to use a grid of labels. This can give an attractive appearance and one or more columns could be right-aligned. Using the Controls property of the user form, you can treat the grid as a two-dimensional array. I have used this technique long ago and found it attractive and not particularly difficult.
In order to set the alignment of a specific column to the right, trying the opposite way might help you:
Set TextAlign attribute of the listbox to "3-fmTextAlignRight".
Add spaces at the END of the each data in the column of sourcearray, which you want to align LEFT. The number of added spaces should be so large as to exceed the width of the column in which the data appears. You don't have to mind whether the number fits to the columnwidth (overflown spaces do no harm). You may prefer to use & String(30, " ") instead (30 is just for example) .
If added spaces seem to be wholly ignored (i.e. data appear right-aligned only), further add any single character (such as "_") at the end of the spaces.
This is a cosmetic solution, but works when seeing left-aligned figures is too annoying.
After doing the above, please be careful when selecting from the list (trimming the added spaces, keeping BoundColumn data intact, etc.).
This trick works for both Excel and Outlook (not sure for other applications).
Test result in Outlook VBA (...trailing 50 spaces are added to data in column 1 and 4.)
Hope this helps.

ActiveX Combobox value not setting to linkedcell on another sheet on workbook_open

We have created a workbook which use ActiveX objects and macros to perform multiple actions (calculations, changing values in cells, forcing mandatory fields before save, colour changes, lock and unlock, etc). There are 3 sheets:
Lists - where we set the values for comboboxes, run mandatory checks against cells and comboboxes, etc. this is VeryHidden to the user
Form - this is where the user will enter their data. it contains all of the ActiveX objects
Import - this is a formatted sheet which we can import to our database with expected formatting on values (i.e. "inches" instead of "in.H2O#60F", days converted to hours). this sheet is VeryHidden.
This workbook can be downloaded blank from our website and imported back into the database successfully.
What we want to do is download a pre-populated version where "Form" shows data from the database. To do this we are populating the Import sheet with the values (as they are already linked to the comboboxes we need to populate). i.e. ComboA on "Form" is linked to cell A4 on "Import".
We expected the comboboxes with linked cells to the update when we downloaded and opened the pre-populated workbook. When it did not we tried:
Sheets("Import").EnableCalculation = False
Sheets("Import").EnableCalculation = True
Application.Calculate
to force the row to "recalculate" and therefore trigger the linked cell to work as when we manually went into one of the linked cells and pressed enter (or F9) the associated combobox updated.
This was partially successful in that is populated around 1/3 of the comboboxes but not all of them. There does not seem to be an order or data type causing the issue (some Y/N update, others do not. comboboxes A-D will update, then E-G will not, then H will).
We tried Application.CalculateFull as well as:
setting the linkedcells to Dirty
only applying .Calculate to the range on the worksheet
only applying .Calculate to the row on the worksheet (as it is all in one row)
We can manually force each combobox to populate with it's linked cell however given the number of comboboxes and the fact there will be more workbooks like this to build this is not an ideal solution.
We know it is hitting the workbook_Open() event as we put in some MsgBox items and the couple custom populations we do (converting degF to F then pushing to combobox) and that is working fine.
If we open the download, save it (skipping the mandatory fields before save), then reopen it everything populates/selects correctly (which is all the more frustrating).
Any thoughts on why the downloaded version is not acting as expected would be much appreciated.
given the other posts I have seen and the follow up information requested I though more was better. there is a code snippet there - and we found a solution to the issue. needed to add Application.Calculation = xlCalculationAutomatic to the open event before the code provided above. thanks anyways

Copying an Object Across a Workbook

I have a workbook which displays a little coloured box based on some input metrics from another worksheet within the workbook. I want to display these little coloured boxes in an additional worksheet in the workbook. Is there a way to copy a shape across worksheets so that the colour will still update with the metrics rather than using the code again for a separate worksheet?
I essentially want to display this textbox with the coloured boxes/arrows in another worksheet as well.
A pretty dirty way to do something like this would be the Indirect-Picture-Copy-Solution.
Asume the art is at Sheet1 B2:D8 then just input a picture in Sheet2 (the picture doesn't matter, just pick the first you can find)
While the Picture is selected input in the formula bar =Sheet1!B2:D8.
Hope that helps ;)
EDIT
For making it dynamically put in any module:
Public Function testing() As Range
Set testing = Range(Sheet1.Shapes("Dia 1").TopLeftCell, Sheet1.Shapes("Dia 1").BottomRightCell)
End Function
(Make sure to change the names to fit your workbook/sheet/shapes....-names)
Then define a name (I'll pick TETE for this example)
Refers to: =testing()
Then the picture-formula is: =TETE
Whenever the size or position changes, your picture fits to it... still not a good way to solve your problem (to my eye)
Funny fact: making the picture-formula directly to =testing() will just pop an error

How to copy conditionally formatted cells from Calc as a table into Writer

I have a LibreOffice Calc spreadsheet that uses some conditional formatting of cells. I would like to copy it into Writer as a table. The colours/formats of the cells should remain as they were due to the conditional formatting in Calc. Unfortunately when I do that, the formatting vanishes.
How can I copy it keeping the formatting?
Of course the Writer version no longer has to be conditional, but I need to keep current colours.
My work is done so eventually I can do the trick in Calc first (abandon the "conditional" part, and just preserve the formatting as - is). However due to amount of data I would prefer not to do it manually.
Is macro the only way to do that?
Use Insert -> Object -> OLE Object
Choose Create from file
Pick the right .ods file.
If you want to modify further (in my case - I need to create many tables from one spreadsheet as the original file is humongous - up to CL column) - do not tick "Link to the file" option.
After pressing OK, the spreadsheet is inserted as is (cloned and embedded), with the conditional formatting. Can be further modified (e.g. rows/cols can be deleted, hidden or whatever is needed). The conditional formatting remains active.
I personally prefer to copy as an image. This ensures the format is always exactly as it was in the spreadsheet and that no weird OLE/DDE links go wrong.
However, you specifically ask for a table. For that there are three (or 2.5) options:
Insert the entire as spreadsheet as an object. In Windows that can be done as Ister describes in his answer. This will be editable as an inline mini-sheet (Writer will invoke Calc for any editing actions).
Insert a part of the sheet as an object: Select what you want in the document, copy to the clipboard, go to Writer and select Edit->Paste Special. Then select the OLE option, or if on Linux, select "calc8". This will be editable as an inline mini-sheet.
Insert as HTML. This creates a standalone table. Formatting will not be 100% as in the sheet, as fonts, etc, will be reset by Writer, but it is a native Writer table that you can manipulate in Writer without invoking Calc. Colors, etc, are preserved.
If you use any of the object embedding options, you'll notice that formulae are kept intact (when not referring the data outside the pasted sheet or region). If you want all the data to be verbatim, then you need an intermediate step:
Select the data in your original sheet that you wish
Copy to the clipboard
Create a new sheet and place the cursor in the same spot as the first cell of the copied data (e.g. if your copied region is B4:X99, then place the cursor in B4 of the new sheet)
Select Edit->Paste Special
In the Paste Special window, check only the following options and click OK:
Text
Numbers
Date & Time
Formats

Show Cell Range on UserForm; then update

I've been using a crude method to help the user update some cells - by having them in a sheet. Is there any way I can display the various ranges in a userform, one by one, then have the user update them, click a button and move onto the next one?
Essentially, can I have Excel automatically generate an input form based on a range? The process of updating and saving back to the sheet I can do; it's the production of the correct form that I can't.
It's possible to do this, but the only way I can think of is to make a userform that automatically populates itself based on a range passed in. This way you could have different macros in Excel that call the form to populate based on different ranges. I built a proof of concept Excel file for trying this, and it seems to work, the only issue I can think of being that you need to figure out a way to tell the user what input field is what.
I think what needs to be done is to add controls programmatically to a userform (I name the textboxes as the cell address it's going to populate) then when the form is closed loop through all the textboxes and populate the cells with the textbox values.
You can see what I did at:
https://my.syncplicity.com/share/uicgbs3rl0/InputForm.xls
I think all that would need to be done is for you to work out how to add labels for the textboxes, and make sure the form is resized based on the controls you add...
I am not quite shure what you are looking for, but you could insert a second sheet and use it as a "form". An other way could be a dialog box with an input field.
Either way, you present the cells you want the user to change one by one, using a vba-function. You implement a "previous field" and a "next field" button, so the user can step through the range of cells. If the user hits "next field", you save his input and take the next cell from a previous defined range of cells.
You could have a "config field" in which you define the range of cells you want to change.
This is pretty rough and old-fashioned but if you have the data in standard list format - i.e. column headers in the first row of your range and then one record of data in each row below - then selecting a cell within the range and going Data > Form will give you a crude input form with roughly the functionality you need.
You can also do this in VBA by calling the ShowDataForm method of the appropriate worksheet. Just select a cell within whichever range you need first. The macro will remain paused until the user closes the data form