i made a chart on my excel sheet, and i want the user not to be able to delete it...
how can i do it?
I already tried this options from here:
https://peltiertech.com/Excel/ChartsHowTo/ChartProtection.html
The code is like this:
'Draw a chart
Dim rng As range
Dim cht As ChartObject
'Your data range for the chart
Set rng = Worksheets("Sheet1").range("$A$2:$A$100")
'Activate chart
Worksheets("Sheet1").ChartObjects(1).Activate
'Populate chart with data
ActiveChart.SetSourceData Source:=rng
'Determine type
ActiveChart.SeriesCollection.NewSeries.ChartType = xlLineMarkers
'Delete the 5th series
If ActiveChart.SeriesCollection.Count = 5 Then
ActiveChart.SeriesCollection(5).Delete
End If
I need something like this:
ActiveChart.preventDeleting
Now, the protection I had in mind was to prevent the user, from actively deleting the chart....a simple select and remove, or button press delete, or something...
In simple terms, block any attempt to delete the chart...
But, i dont know if this is relevant, but the table can change its range, and the chart should be still able to get updated...
Please let me know, if you need something else...
Also, it does not nessesary need to be a vba code, it can also be a manual solution, I am using MS excel 2007
Thanks...
You can protect the chart by protecting the sheet. If you want the user to be able to edit some of the cells, simply right click on the cells that you want to be able to be edited and select Format Cells -> Protection -> Locked and make sure this is unchecked.
Then protect the worksheet via Review -> Protect Sheet on the menu bar. This will prevent the deletion of the chart and allow users to continue editing the cell content
Related
I want to be able to control and update the source (range) of an excel chart through VBA. The chart is ultimately going to be presented in a powerpoint presentation and the whole process shall update automatically.
I have tried using tables which doesn't give me the level of control I want. For example if i delete one datapoint the chart doesn't "shrink" accordingly.
ActiveChart.SetSourceData (Sheets("Sheet2").Range("E5:E9"))
The current script doesn't run. But I just want to "set" a source range for a particular chart, preferably accessed by name. And if new datapoints are added I just run the script again and the new range will be the top cell in the column down to .End(xlDown)
Thanks guys! I manged to find a solution that works for me and made a function of it, if anyone else has the same problem. Nothing fancy but you can set a range like "A2:A14" and the chart will update with the new range. The function is called by sheet name, chart name and range like below:
Call changecharts("Sheet2", "Chart1", "A2:A11")
Public Function changecharts(sheeet As String,chartname As String, rnge As String)
Worksheets(sheeet).ChartObjects(chartname).Activate
With ActivateChart
ActiveChart.SetSourceData Source:=ActiveWorkbook.Sheets(sheeet).Range(rnge)
End With
End Function
I’d like to write visual basic code that adds a “new series” to an existing plot. I’ve already managed to write the code that will select that data I want to add. So to complete the operation I did it in excel, recording the following macro:
‘desired data already selected a column of x values and one of y values to be plotted
Selection.Copy
Sheets("XVSER").Select
ActiveSheet.ChartObjects("Chart 3").Activate
ActiveChart.Paste
However, what this recorded macro does not show is I wanted to add the data as a “new series”, even though this option was explicitly selected while recording the macro. So when I run the macro it does not do the same thing I did will recording it, and adds the data to an existing series instead of creating a new series for it.
Surely there must be a way of specifying in VBA that I’d like a new series. I just don’t know how, or where to find documentation, and what I found already on stackoverflow, was difficult for me to understand, and seemed to require a different approach, which I’d rather avoid, since I’ve already developed the code to successfully select the data I want, and to select the chart I want to paste it in.
When recording MACROS with charts, not allways the result comes out the same as when recorded it. You will need to familiarize yourself with some of the ChartObject properties.
Try the code below:
Option Explicit
Sub AddSelectionasNewSeries()
Dim ChtRng As Range
Dim ChtObj As ChartObject
Dim Ser As Series
' set the selection as range >> However, try avoid using slection
Set ChtRng = Selection
' set the chart object
Set ChtObj = Sheets("XVSER").ChartObjects("Chart 3")
' add a new series with the Selection
ChtObj.Chart.SeriesCollection.Add ChtRng
End Sub
You have to use SeriesCollection.Paste, which has parameters to specify whether to add points or series and so forth. The Macro Recorder doesn't know this.
Replace
ActiveChart.Paste
with
ActiveChart.SeriesCollection.Paste Rowcol:=xlColumns, Serieslabels:=False, _
CategoryLabels:=True, NewSeries:=True
I would like to use VBA to paste a range of data into an existing chart, using the options shown in the following screenshot:
If I record a macro whilst doing so manually, the code only states ActiveChart.Paste. Thus, when I re-run this code the series is pasted regularly without the 'Series Name In First Row' deactivated. How can I code this correctly? I haven't found much in the way of help in my research so far.
Well, I tried a simple code and it works.
Suppose you have a data like below and you made a simple Clustered Column Chart:
Now you want to paste special Data2 as in your screen shot.
VBA code which works at my end is below:
Sub test()
Dim ch As Chart: Set ch = Sheet1.ChartObjects(1).Chart
Range("A1:A4,C1:C4").Copy '~~> you need to include the x axis labels when copying
ch.SeriesCollection.Paste RowCol:=xlColumns, SeriesLabels:=False, _
CategoryLabels:=True, Replace:=False, NewSeries:=True
End Sub
Result:
I don't know what chart you're working on or how you want it constructed.
Above just shows how to execute Copy and Paste Special of data from a Range to an Existing Chart. HTH
Seems simple and probably a case of "It's monday" but I can't find the answer to this.. without having to record all the pagesetup variables in strings beforehand, is there a way to copy a worksheets .pageSetup property?
in a macro im running, I create a new page, paste some data, change a bunch of pagesetup settings, then print. I was hoping there was a way i could save the page setup before hand, and apply it again afterwards so my users don't have to worry about fixing settings ever.
I tried:
dim ws as worksheet
set ws = ActiveSheet.pageSetup
'settings change / print
ActiveSheet.pagesetup = ws.pagesetup
that doesnt work because ws.pagesetup is now linked to activesheet.pagesetup, so as soon as i change the active sheets settings, ws's settings get changed too.
I also tried set ws = sheets(1) because the new page is never the first page, but then with that one ActiveSheet.pagesetup = ws.pagesetup doesnt work either, it says object doesn't support this property or method
Is there a simple way? must I have 20 different string variables to hold all the current pagesetup variables?
Thanks
When I want to accomplish something like this I'll save all my formatting and pagesetup stuff to a hidden sheet. At the right time I'll have my code copy and paste everything where I need it. In this case it would probably be easiest to start by making a copy of the hidden sheet. Then dump in your data and work from there.
Rather than coping page setting from a master sheet to other sheets:
Create the master sheet
Establish the page settings for this single sheet
Make copies of the master
Populate the copies with data, formulas, etc.
In other words, anticipate your needs and setup the sheets in advance.
I've got an Access 2007 database on which I have created around 15 SQL queries to process specific data, I have created a main frame navigation menu using menus in Access, I now need to extract all th queries to Excel using VBA code, I have managed to do this with the code below by creating a button and specifying this code to it.
Private Sub query1_Click()
DoCmd.TransferSpreadsheet acExport, _
acSpreadsheetTypeExcel9, "Total Users and Sessions", _
"C:\UsersandSessions.xls", , "Total Users & Sessions"
End Sub
Now my problem at the moment is that fine the query is exported to Excel, but it is done so without any formatting applied at all, I would like to add some formatting at least to the headers and maybe a title inside the spreadsheet, and one thing I dont really like is that all records are being started from the first cell. Also I would prefer that if I hit that button again in Access and the Excel spreadsheet has already exists with that query output then when clicked again it will write again to a the next available sheet.
Any suggestions or ideas a very welcome.
The short story, is you can't. You might be able to do some scripting on the Excel side to format the resulting file. If you want something pretty, you probably want to create a report.
You could, instead mount the excel sheet as a table, and then on a separated sheet in the excel file, reference the first sheet, and format the second sheet for viewing.
if you use DoCmd.TransferSpreadsheet and create an original and then edit it so that the formatting is correct, you can then run DoCmd.TransferSpreadsheet again and it will update the file with the values but keep the formatting.
However, if a human then changes the file by adding new tabs, or adding calculations, etc, then the DoCmd.TransferSpreadsheet will no longer work and will fail with an ugly error message. So what we do in our enviroment is DoCmd.TransferSpreadsheet to an original file with formatting, and follow that up in the VBA by copying the file to the users desktop, and then opening that copy so the user doesn't mess up the original source excel file.
This approach is a minimum code, clean, and easy to maintain solution. But it does require a extra "source" or original file to be hanging around. Works in Access 2007.
You also would like the results to end up on a new tab. Unfortunately, I think it will take some excel automation to do that. The VBA inside Acccess can call a function inside the VBA in Excel. That VBA could then copy the tabs as needed.
My idea would be a hybrid of Excel automation from Access and creating a template in Excel as well that would have a data table linked to your query.
To start create your data table in Excel. You can start three rows down and two columns to the right if you want or wherever. Go to your data tab and click access, find your db, choose your query you want to link to, choose table as the radio button but click properties next instead of ok, uncheck the enable background refresh, this part is critical ... under the definition tab in the connection string you will see a part that says Mode=Share Deny Write change that to Mode=Read, this will make sure that the query refreshes without errors from an MS Access VBA while the db is open and will keep your users from writing back to the db in case your query is a writeable query. Once you set that up you can adjust the table formatting however you choose from the table design tab and it will keep that formatting.
For the purposes of this we are going to assume you started the table in cell B4 ,and your named the worksheet CurrentDay, for purpose of the following VBA example be sure to replace that reference with your actual placement.
Next go back to Access and write your VBA first ensure that in your VBA window you have the reference to Microsoft Excel 12.0 Object Library is selected by going to Tools > References and selecting it from the alphabetical listing.
Create your sub as follows:
Sub query1_click()
Dim xl as Excel.Application
Dim wbk as Excel.Workbook
Dim wks as Excel.Worksheet
Dim RC as Integer
Dim CC as Integer
Set xl = New Excel.Application
Set wbk = xl.wbk.Open "X:\Filelocation\FileName.xlsx" 'name and path you saved the file you previously created
xl.Visible = True
'The above is not necessary but you may want to see your process work the first few times and it will be easier than going to task manager to end Excel if something fails.
RC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("B:B")) + 3 'This will count the rows of data in your table including your header so you can copy the data to another tab dynamically as the size of your table expands and shrinks we add 3 to it because we started at row 4 and we need the location of the last row of the record set.
CC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("4:4")) + 1 'This counts the header row and adds one space because we will use this as a location holder for our copy / paste function
Set wks = xl.wbk.Worksheets.Add
wks.Name = format(date(),"MM_dd_yy") 'this will name the tab with today's date... you can eliminate this step if you just want the sheets to be the generic Sheet1, Sheet2, etc.
With xl.wbk
.Worksheets("CurrentDay").Range(Cells(4,2),Cells(RC,CC)).Copy
.wks.PasteSpecial xlPasteValues 'This pastes the values so that the table links do not paste otherwise every tab would just refresh everyday.
.wks.PasteSpecial xlPasteFormats 'This gets your formatting.
.RefreshAll 'This will refresh your table
Wend
With xl
.Save
.Close False
.Quit
Wend
Set xl = Nothing
Set wbk = Nothing
Set wks = Nothing
End Sub
That should get you to have your data to not start on A1 of your sheets, save your old data each time, and automate the steps from access.