How to enable Grouping on a protected Excel 2007 sheet - without macros - excel-2007

I have an Excel 2007 XLSX workbook I am developing. It has multiple sheets and most of those use Excel's Grouping feature. I want to be able to protect the sheets, to protect some formulas and such from user intervention, but it seems there's no way to do that and still allow the user to expand or collapse the Grouped columns whenever they want.
It appears the standard answer on this is to insert a macro with commands like:
ActiveSheet.EnableGrouping
ActiveSheet.Proect UserInterfaceonly = true
But this workbook has no macros now and cannot have any ever. Is there a way to do this in Excel without a macro?
Thanks!

If there is nothing preventing you from running the code externally, then just put this code into another macro enabled workbook OR run it from a seperate C# winform/console application exe.
Note I had quick search of the Excel 2007 object model and didn't find the EnableGrouping method, but maybe i wasn't looking hard enough.
External VBA
Sub UpdateWorkbook()
Constant workbookpath As String = "C:\somepath\someworkbookname.xlsx"
Dim wkbk As Workbook
Set wkbk = Application.Workbooks.Open(workbookpath)
Dim wksht As Worksheet
Set wksht = wkbk.Worksheets.Item("sheetname")
wksht.EnableGrouping
wksht.Protect UserInterfaceonly = true
Set wksht = Nothing
Set wkbk = Nothing
End Sub
External C#
public void UpdateWorkbook()
{
const string workbookpath = #"C:\somepath\someworkbookname.xlsx";
Excel.Application xlApp = New Excel.Application();
// To use the next line you need the Excel Extension library otherwise use Type.Missing.
Excel.Workbook wkbk = Application.Workbooks.Open(workbookpath);
Excel.Worksheet wksht wksht = (Excel.Worksheet)wkbk.Worksheets.get_Item("sheetname");
//Check the way this method works..
wksht.EnableGrouping();
// UserInterfaceOnly is the 6th parameter, so 5 before and 11 after.
wksht.Protect(missing,missing,missing,missing,missing,True,missing,missing,missing, missing,missing,missing,missing,missing,missing,missing,missing);
Set wksht = null;
Set wkbk = null;
Set xlApp = null;
}

Related

Access 2007 VBA - Open Two Excel Workbooks

I am using Access 2007. In my Access file I have VBA code that opens an Excel
workbook when the Access program begins. The Excel workbook remains open
while the program is running. I use this code to open the workbook:
Public xl As Object
Public wb1 As Object
Set xl = New Excel.Application
Set wb1 = xl.Workbooks.Open("c:\Book1.xlsx")
Now while the program is running I may need to open a second Excel workbook,
get some data from it, then close it. I used this code:
Public wb2 As Object
Set wb2 = xl.Workbooks.Open("c:\Book2.xlsx")
But this doesn't work. It seems that the first workbook may have closed because
if I do debug.print Workbooks.Count the response is "0".
Any suggestions on how to open a second workbook and still have the first workbook open?
Should I create a second instance of Excel and use that to open the second workbook?
Thank you.
You may have more luck with this procedure instead:
Sub OpenExcel(fName As String)
Dim xlApp As Object
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
'Excel wasn't running, start it from code
Set xlApp = CreateObject("Excel.Application")
End If
On Error GoTo 0
xlApp.Workbooks.Open (fName)
End Sub
With your code it's possible that Excel was opening but the second workbook did not default to visible, which could be set with xl.Visible = True. Alternatively, a second xl object could have helped.
Regardless, this method is safer is a number of ways.
Make sure when you're done, make sure you clean up (and free up memory) with something like xlApp.Quit and Set xlApp = Nothing.
In fact, I'd suggest you reboot right now... before you do, take a look at the running processes in your Task Manager - I wouldn't be surprised if you have several "invisible" instances of Excel running. :)

Manipulate a word document ("caller"/"context") from an excel workbook ("callee"/"controller") that was opened by it

Background
I have a Word-macro in Normal.dotm that opens an Excel-workbook Reference Check.xlsm.
The macro uses RegExp as well as Range.Find to find strings of a certain pattern, and then it places this information onto sheets in the Excel-workbook.
This is the basic template:
Sub GetReferencesAndHyperlinksToExcel()
' Shortcut Key: Ctrl+[Num *]
Dim oRegex As New RegExp
Dim oRegExMatches As MatchCollection
Dim oRegExMatch As Match
Const strPattern As String = "(my pattern)"
Dim SourceDocument As Document
Dim oStory As Range
Dim hl As Hyperlink
Dim xlApp As New Excel.Application
Dim xlWorkbook As Excel.Workbook
Dim R as Excel.Range
' Set the context
Set SourceDocument = ActiveDocument
' Load the spreadsheet
Set xlWorkbook = xlApp.Workbooks.Open("C:\...\Reference Check.xlsm")
' Set starting range to write to
With xlWorkbook.Worksheets("Reference Checks")
.Range("ref").ClearContents
Set R = .Range("ref")(1, 1)
End With
' Initialise regex
With oRegex
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
' ==== Iterate through story ranges, then execute regex and write matches and hyperlinks to the spreadsheet ====
' ==== Iterate through story ranges, then iterate through hyperlinks and write hyperlinks to the spreadsheet ====
End Sub
The Excel-workbook does some calculations and lookups (with pre-filled column formulas) against a Data Table within the Workbook.
Using that information, I manipulate the active Word document (the "caller" or the "context") in predictable^ ways.
^If it's predictable, then we should be able to use a macro to do the work for us.
The problem
I want to use the now-open Excel workbook Reference Checks.xlsm as a "console" or "controller", where I can change some data, and use data, to perform operations on (make changes to) the document.
To do this, I believe I need to somehow be able to refer to the original "caller" or "context", i.e. the Word document that was Active when I originally called it (Set SourceDocument = ActiveDocument), from within the now-open Workbook. This means that either:
Macros within Excel (tied to Buttons) Reference Check.xlsx act on SourceDocument (preferred), or
Macros within Excel (tied to Buttons) Reference Check.xlsx call a Macro within Word Normal.dotm and then act on the SourceDocument* (if this is possible, the above should be), or
Various macros within Normal.dotm act on SourceDocument* (workable, but clunky)
*Note: This must actually be SourceDocument (the "caller" or "context") and not ActiveDocument, because it is possible that as I switch between windows, another document could become ActiveDocument.
Things I've thought of
For option 1, use a global variable in Reference Checks.xlsm, then when I load the workbook, set the reference to SourceDocument. This is my preferred option. I have no idea how to do this, however.
For option 3, use a global variable in Normal.dotm, set the reference to the workbook when I open it, then read information in the workbook when I call the macros. A drawback would be that I have many macros I might call, and I would have to have many public subs (makes Normal.dotm quite unwieldy).
Help
How do I do this?
I have tested this and it worked perfectly with Office 2010.
Note that you need the Excel Library in your Word Normal Template and the Word Library in the Excel Reference Check.xlsm
You will need the following:
Sub in the ThisWorkBook module in the Reference Check.xlsm.
So in your Excel VBA Project -> Microsoft Excel Objects -> ThisWorkBook
Option Explicit
Sub ExcelWordController(WordDocFromWord As Document)
'If you are wanting to use it as a Document then _
you will need the Word Library in Excel
MsgBox WordDocFromWord
'Just put some funny text inthe doc for a test
WordDocFromWord.Range(0, 0).Text = "Yeah Baby It works"
'Here you can then call someother Sub or so some processing
End Sub
Then in your Word Normal project:
Option Explicit
'Sub in Word Normal
Sub ExcelControlWordFromWordInitiation()
'Obvisouly you alrady have the Excel Library in the Word Doc
Dim xlApp As New Excel.Application
'xlWorkbook is a object in the Word Excel Library
'So I changed the name
Dim RefCheckWorkBook As Excel.Workbook
Dim R As Excel.Range
Dim SourceDocument As Document
Set SourceDocument = ActiveDocument
'You want to be able to see the Excel Application
xlApp.Visible = True
Set RefCheckWorkBook = xlApp.Workbooks.Open(Environ("USERPROFILE") & "\Desktop\Reference Check.xlsm")
'Calling the Sub in Excel from Word
Excel.Application.Run "ThisWorkBook.ExcelWordController", SourceDocument
End Sub

Powerpoint VBA to switch back to powerpoint from Excel

I hope someone can help....
I have a powerpoint presentation, which has linked tables and graphs from an excel file. the updating of the slides are set to manual.
i have created a VBA code in Powerpoint which opens up the excel file. I am trying to update the links in the powerpoint through VBA instead of manually choosing each linked element and updating the values. while the first part of my VBA code works in opening up the excel file, the links are not being updated, which i think is down to not being back in the powerpoint to update the links, so I am trying to include in my VBA code lines which will go back to the powerpoint presentation, after which i assume the the line to update links will work (happy to be corrected). below is the code i have built so far....my comments are in bold ...
any suggestions?
FYI, I am using office 2007.
Thanks
Sub test()
Dim xlApp As Object
Dim xlWorkBook As Object
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
Set xlWorkBook = xlApp.Workbooks.Open("File location\filename.xlsm", True, False)
Set xlApp = Nothing
Set xlWorkBook = Nothing
Section above opens the excel file which contains the linked tables and charts
On Error Resume Next
With GetObject(, "PowerPoint.Application")
.ActivePresentation.SlideShowWindow.Activate
End With
Section above i was hoping would go back to the powerpoint after opening the excel file but it does not which is why i think the code below to update links is not working
ActivePresentation.UpdateLinks
End Sub
Start from something easier. This will allow you to activate the first existing PowerPoint application from Excel:
Option Explicit
Public Sub TestMe()
Dim ppt As New PowerPoint.Application
ppt.visible = msoTrue
ppt.Windows(1).Activate
End Sub
Then play a bit with it and fix it into your code.
#Vityata
Ok, i got it to work....original coding did the first part of opening the excel file, and to switch back to powerpoint (and i think this will only work if there is only 1 presentation open i added the following code...
AppActivate "Microsoft PowerPoint"
so my complete code looks like:
Sub test()
Dim xlApp As Object
Dim xlWorkBook As Object
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
Set xlWorkBook = xlApp.Workbooks.Open("file path\file name.xlsm", True, False)
Set xlApp = Nothing
Set xlWorkBook = Nothing
AppActivate "Microsoft PowerPoint"
End Sub
now to get manual links to update as part of the vba code...
If you capture the file that your macro is in. This is just a string of your path and filename
'This is the macro file
MacroFile = ActivePresentation.FullName
Then you can use that variable to activate just that specific PowerPoint presentation.
Use Presentations(MacroFile).Activate
or Presentations(MacroFile).Updatelinks
It's best not to use ActivePresentation when moving between applications.

How To Develop My Own Excel Add-in in VB.Net

I am trying to create an Excel Add-in using Vb.Net. I've started an Excel 2007 Add-in Project in VS2010. Sadly, I am not good with vb.net; I am more a VB6 developer in this regard, and my ThisAddin.vb code is:
Public Class ThisAddin
Private Sub ThisAddIn_Startup() Handles Me.Startup
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
End Sub
' test function; simple
Public Function getRowCount() As Long
Dim thisWB As Workbook = Me.Application.ThisWorkbook
Dim activWS As Worksheet
activWS = thisWB.ActiveSheet
Return activWS.UsedRange.Rows.Count
End Function
End Class
I've also added a Ribbon item (via Add New Item... menu option) in designer mode (not xml) - and then add a button. Then I go to code and try to call the function and I get this error when using:
MsgBox(Globals.ThisAddIn.getRowCount())
Which I got from this link: Calling a procedure within another class
To be honest, I've been trying a myriad things and I've been getting so many errors. I've been looking online as well for a tutorial on creating my own Excel Addin from scratch with no real luck. I would like not to use Add-In-Express since that's a third party app and I have to create an Excel add-in for my company from scratch.
Does anyone have an idea on how I can create a vb.net coded Excel Addin (2007) that I can use as a template or guide? I've tried several and many rely on Add-In-express and I really cannot go that way. I have a lot of VBA code (natural VBA so it's in a module in an my excel files' VBA/Developer section) and I think I can translate those from VBA/VB6 to VB.Net format so that's not my concern. It is really about getting to code my own Excel Addin in VB.Net. Any help would really be great. Thank you.
*note: I would also like not to have to ask coworkers (or do myself) to just add to the quick access toolbar the functions and subs I've created since that's really not a solution, considering that those buttons will be there when they create or open another workbook. Essentially, I've got to create my own excel addin in vb.net. Thank you once again.
The issue has to do with the definitions in Microsoft.Office.Tools.Excel and Microsoft.Office.Interop.Excel. To code an "Interop" version you could use this:
Public Function getRowCount() As Long
Dim thisWB As Excel.Workbook = Application.ActiveWorkbook
Dim activWS As Excel.Worksheet = CType(thisWB.ActiveSheet, Excel.Worksheet)
Return activWS.UsedRange.Rows.Count
End Function
To extend the functionality of the Native objects and use VSTO, you could do it like this:
Public Function getRowCount() As Long
Dim NativeWorkbook As Excel.Workbook = Application.ActiveWorkbook
Dim NativeWorksheet As Excel.Worksheet = CType(NativeWorkbook.ActiveSheet, Excel.Worksheet)
Dim thisWB As Workbook = Nothing
Dim activWS As Worksheet = Nothing
If NativeWorkbook IsNot Nothing Then
thisWB = Globals.Factory.GetVstoObject(NativeWorkbook)
End If
If NativeWorksheet IsNot Nothing Then
activWS = Globals.Factory.GetVstoObject(NativeWorksheet)
End If
Return activWS.UsedRange.Rows.Count
End Function
This is a function you can put in ThisAddin.vb that will create a new Worksheet. Note that this function names the Worksheet and adds it to the end.
Public Function AddWorkSheet(sheetName As String) As Worksheet
Dim wk = Application.ActiveWorkbook
Dim ws As Worksheet = Nothing
Try
ws = CType(wk.Sheets.Add(, wk.Sheets(wk.Sheets.Count)), Worksheet)
ws.Name = sheetName
Catch ex As Exception
Throw
Finally
AddWorkSheet = ws
End Try
End Function
To use this outside of ThisAddin.vb you could do something like this:
Dim ws As Excel.Worksheet
Dim newSheetName As String
.
'
ws = Globals.ThisAddIn.AddWorkSheet(newSheetName)

VBA: Reading excel data into word

I am making a simple form that extract the data from my excel sheet, such as name, date of birth, and address. And inserting them into my word form, I am doing 20-30 sheets everytime, so I think it might be able to save the copying & pasting time.
I tried to follow this tutorial: http://www.makeuseof.com/tag/integrate-excel-data-word-document/
And created a button with a simple label named m_name, for member's name. But it tells me Compile error: User-defined type not defined. And flaged on line 1.
I am using Word 2003, (I am not able to find the Tools > Reference as the guide was asking for). I am not sure if it is related to this error.
Private Sub CommandButton1_Click()
Dim objExcel As Excel.Application
Dim exWb As Excel.Workbook
Set exWb = objExcel.Workbooks.Open("U:\test.xls")
ThisDocument.m_name.Caption = exWb.Sheets("Member's Data").Cells(3, 3)
exWb.Close
Set exWb = Nothing
End Sub
Yes, it's very important to set references according to the tutorial.
However, change these two lines:
Dim objExcel As Excel.Application
Dim exWb As Excel.Workbook
to:
Dim objExcel As Object
Set objExcel = CreateObject("Excel.Application")
and the code should work, too.