VBA causing typed information to go to an incorrect worksheet - vba

I am creating a spreadsheet that creates a reference number on the first worksheet (called database, to be used similarly to a database) and generates a new worksheet. This then gives a reference number on the new worksheet so that they are linked together. This is done by pressing "New Idea" on a UserForm.
Once this is completed it should then go to the newly created worksheet and highlight cell C7. Once this is complete it should close the UserForm and allow the user to be able to type in cell C7 on the new worksheet with no further steps needed.
This works fine if I use F8 to step through the process however if I close the code window and run through the process as a user would it doesn't work as it should.
C7 is highlighted but once you have typed in it and press enter to go to the cell below, what you've typed disappears completely, and whatever you type on the newly generated worksheet is actually entered on another worksheet.
I have a seperate worksheet that contains a button to open the UserForm and all data that is entered on the newly generated worksheet goes to this sheet incorrectly.
My code is below, and is all within the UserForm's code. I have left the ComboBox code below but this isn't relevant to the generation of the new worksheets. All that does is list the created tabs so the user can select a worksheet from the UserForm and go directly there rather than having to scroll sideways.
I'm using Excel 2013. I'm by no means a VBA veteran so any help would be greatly appreciated!
Thanks!
Private Sub UserForm_Initialize()
Me.ComboBox1.List = Worksheets("Database").Range("A2:A10000").Value
End Sub
Private Sub CreateNewIdea_Click()
CopySheet
End Sub
Sub CopySheet()
Dim LastRow As Long
NewReference
LastRow = Sheets("Database").Range("A" & Rows.Count).End(xlUp).Row - 1
ReturnValue = LastRow
Sheets("Idea Template").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = LastRow
Range("C3").Value = LastRow
Me.ComboBox1.List = Worksheets("Database").Range("A2:A10000").Value
Range("C7").Select
Unload Home
End Sub
Sub NewReference()
Dim LastRow As Long
LastRow = Sheets("Database").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Database").Cells(LastRow + 1, "A").Value = Sheets("Database").Cells(LastRow, "A").Value + 1
End Sub
Private Sub ComboBox1_Change()
Worksheets(ComboBox1.Text).Select
End Sub

I've taken the liberty to edit and rewrite the code you've written for greater flexibility.
Option Explicit 'Forces the variable to be declared, undeclared variables are not allowed
Dim DatabaseTable As ListObject 'Makes the variable usable for the entire module
Dim Lastrow As Long
Private Sub UserForm_Initialize()
Set DatabaseTable = ThisWorkbook.Worksheets("Database").ListObjects("References")
'I'm assuming you've formatted the data on the worksheet as a table and named the table "References"
Dim i As Long
Dim DatabaseRows As Long
DatabaseRows = DatabaseTable.ListRows.Count
With Me.ComboBox1
.Value = Empty
.Clear
For i = 1 To DatabaseRows
.AddItem DatabaseTable.DataBodyRange(i, 1)
Next i
End With
End Sub
Private Sub CreateNewIdea_Click()
Set DatabaseTable = ThisWorkbook.Worksheets("Database").ListObjects("References")
Call CopySheet
End Sub
Sub CopySheet() 'Are you calling Sub CopySheet() from other subs besides Private Sub CreateNewIdea_Click()?
Call NewReference
Dim ReturnValue As Long 'I'm declaring this variable because I'm using the option explicit and that doesn't allow undeclared variables
ReturnValue = Lastrow 'Unless ReturnValue is a public variable, it's not doing much here.
ThisWorkbook.Worksheets("Idea Template").Copy After:=ThisWorkbook.Worksheets(Worksheets.Count)
ThisWorkbook.Worksheets("Idea Template (2)").name = Lastrow
ThisWorkbook.Worksheets(CStr(Lastrow)).Cells(1, 3).Value = Lastrow 'Cstr(lastrow) is needed because we want the sheet with the name of the last row, not the nth sheet which is what happens with WorkSheets(Lastrow) as lastrow is a number
Call UserForm_Initialize 'Calls the procedure which fills ComboBox1, if the unload home refers to this form, then this line is redundant since the combobox is filled again when the form is initialized.
ThisWorkbook.Worksheets(CStr(Lastrow)).Cells(7, 3).Select
Unload Home 'If the name of this form is home, you can just 'Unload Me'
End Sub
Sub NewReference() 'Are you calling Sub NewReference from other subs besides Sub CopySheet()?
DatabaseTable.ListRows.Add AlwaysInsert:=False 'Adds a new row to the table on the worksheet "Database"
Lastrow = DatabaseTable.ListRows.Count
If Lastrow = 2 And IsEmpty(DatabaseTable.DataBodyRange(1, 1)) Then 'This if determines if a row was added while the first row does not contain a reference
DatabaseTable.DataBodyRange(Lastrow, 1).Value = 1 'First reference, can be anything you want really
DatabaseTable.ListRows(1).Delete 'First row is deleted, otherwise you'd have an empty first row
Lastrow = Lastrow - 1
Else
DatabaseTable.DataBodyRange(Lastrow, 1).Value = DatabaseTable.DataBodyRange(Lastrow - 1, 1) + 1
End If
End Sub
Private Sub ComboBox1_Change()
If Not Me.ComboBox1 = Empty Then
Worksheets(CStr(Me.ComboBox1)).Select
End If
End Sub
Revised answer
After looking at the document provided by #tomjo and trying to reporduce the problem I found that the problem was caused by the buttons on the sheets. The buttons used were the Form Controls rather than ActiveX Controls.
A macro was assigned to the Form Control The macro was defined in a module as you'd expect. The Macro only called to show the relevant form. It appeared as if the selected sheet, either by the menu on the form or after creating a new sheet from the form wasn't properly activated and the information entered in the sheet that showing was actually entered in the form which was last manually selected. Stepping through the code I found that the proper sheet and cell was active after the selection through the form through Debug.Print ThisWorkbook.ActiveSheet.Name, ThisWorkbook.ActiveSheet.ActiveCell.Address. I failed to discover why, while the correct sheet and cell were active, the information was entered in the last manually selected worksheet and cell.
To verify that the issue was not caused by the file somehow I tried to reproduce the problem with an entirely new file. Again the problem occurred that while the screen was showing the correct sheet and cell as selected (selected through a form, called by a sub in a module, called by a Form Control) the information was actually entered in the last manually selected sheet and cell.
----Edit----
Running the Showform macro (which calls the form to show) from the Macros button under the developer tab in the ribbon, instead of clicking the Form control button which has the ShowForm macro assigned to it, doesn't create the issue.
----End of Edit----
I then only removed the Form control, and the sub in the module which calls to show the form and placed an ActiveX Control (CommandButton) on the sheet and on the relevant Sheet module created:
Private Sub CommandButton1_Click()
Form.Show
End Sub
Without editing the code any further, there were no further issues regarding information being entered on the last manually selected sheet and cell instead of the sheet and cell the screen was showing as selected.
Edited file (The link will be active for a limited time)

Related

VBA Several UserForms export to Sheet

In my Workbook i have several identical UserForms. Only the name is different.
For Example WKA1 / WKA2 / WKS1 / WKS2 / PM1 / PM2 and some more.
Now i want if i click on the CommandButton on the UserForm, that the Data in the TextBoxes will be saved on a extra Worksheet. I want that with a seperate Macro, so that i code for the CommandButton looks like this:
Private Sub CommandButton1_Click()
Call Save_UF_Data
[NameOfUF].Hide
End Sub
The Problem is, i donĀ“t know how to write in the Macro "Save_UF_Data" that it always takes the TextBox from the UF which is open.
I already tried it with:
Me.Controls("TextBox1")
I hope someone can show me how i have to write the code that my macro will work for every UserForm in my Workbook.
This is my Macro so far:
Public Sub Save_UF_Data()
Dim lastrow As Long
Dim a As Integer
Dim ws As Worksheet
Set ws = Worksheet("UserForm_Data")
lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
a = 1
Do
ws.Range("A" & lastrow).Value = Me.Controls("Label" & a) ' How do i have to change this part that it takes the value from the userform which is open?
a = a + 1
lastrow = lastrow + 1
Loop Until a = 25
End Sub
You could pass the calling form Object as Parameter to the Sub:
Private Sub CommandButton1_Click()
Call Save_UF_Data(Me)
[NameOfUF].Hide
End Sub
And the Sub would look like:
Public Sub Save_UF_Data(frm As UserForm)
Debug.Print frm.Controls("Textbox1")
(...)
End Sub
Have a look to How to loop through all controls in a form, including controls in a subform - Access 2007 to learn how to access the controls of a form

Creating a Sheet List using Listbox

In a User form using a Listbox1 I would like to make a list of the Opened Workbooks and in the Listbox2 in the same form the sheets of the selected workbook in the listbox1 But also in the lisbox2 I would like to create with each sheet name a checkbox with five command buttons in the form to import, Export, Erase, Hide or Unhide the selected sheets from Wb1 to Wb2 and vice versa.
So far I receive assistance from you guys to make a do a form with a list of opened workbooks and a list of the respective worksheets here also I'm trying to get to work a code to import the sheets from one workbook to another here,. Do you know a Way to make this happen.
thank You
By the way this is the code use from a sheet to erase the sheets that might be put in the list
Sub DeleteSheets()
Dim wks As Worksheet
Dim MyRange As Range
Dim cell As Range
Set wks = Worksheets("Controls")
With wks
Set MyRange = Range("D5:D34", .Cells(.Rows.Count, "H").End(xlUp))
End With
On Error Resume Next
Application.DisplayAlerts = False
For Each cell In MyRange
Sheets(cell.Value).Delete
Next cell
Application.DisplayAlerts = True
On Error GoTo 0
Sheets("Controls").Range("D5:D34").ClearContents
End Sub
And this ones for hide and unhide the sheets:
Sub Hide_Sheets()
'In use
'Hide the sheets in Controls Sheet
Dim cell As Range
On Error Resume Next
For Each cell In Sheets("Controls").Range("E5:E34")
' Hide sheets
Sheets(cell.Value).Visible = False
Next cell
End Sub
Sub Unhide_Sheets()
'In use
'Unhide the sheets in Controls Sheet
Dim cell As Range
On Error Resume Next
For Each cell In Sheets("Controls").Range("G5:G34")
' Hide sheets
Sheets(cell.Value).Visible = True
Next cell
End Sub
I suggest the following structure of your userform:
Since you do what two lists one with workbooks and one with the worksheets of the currently selected workbook. Then you want to have five command buttons for the actions you want to perfom.
In order to update the workbooks and worksheets you will want to place code in the userform inside the Userform_activate and Listbox1_Change events. So You get the code to list all the workbook names into the listbox1 and put it into Userform_Activate. Evertime the userform is activated the list of workbooks will be updated.
If you now select a entry of listbox1 you want the code to update your sheet names. So you get the code to update the sheet names of a workbook with name "wbname" and put it into listbox1_Change. You then do the following code:
Private Sub ListBox1_Change()
Dim wbname as string
wbname=ListBox1.Value
call GetSheetNamesIntoListBox2(wbname)
End Sub
Where of course GetSheetNamesIntoListBox2 is the sub were you get all the sheetnames into ListBox2.
Lastly you need to setup the Buttons. Each Button has a Click Event which you will want to use. So if the Button is clicked the following code will run:
Private Sub CommandButton1_Click()
Dim wbname as string, wsname as string
wbname=Listbox1.Value
wsname=Listbox2.Value
' You may want to check if wbname and wsname are valid before running the Task
PerformAction(wbname,wsname)
End Sub
Where PerformAction is the routine you use to import, export, clear, hide or unhide the sheet.
I know it is no workedout solution but you will be able to adjust this general solution to your specific case. If you run into problems using my approach just ask in the comments.

Using a macro to sort data from instrumentation software

So I use an instrumentation software at work that outputs readings to a csv excel file. Because of the length of the test and the readings every 30 seconds, I accumulate a few thousand rows for every 24 hours of the test. When the test runs, it reads things that I don't need readings of so I have to go through the sheet manually and replace the "false" readings with zeros.
What I would like to do is use a command button to prompt the user to select a column to sort and apply a range of values so if it falls within that range, it returns the value to the cell and if it doesn't fall within the range, it returns a 0. I have done this with smaller sheets with extra columns (see attached file) but I'm not super familiar with Macros or VBA so I'm not sure where to get started.
Can anyone give me a hand?
This can be done as follows.
1) Go to Developer tab in the Excel ribbon. Click Insert, choose a Command Button (ActiveX Control) and place it onto the sheet where you want to have it.
2) Double-click the button, this will open up the editor. You should see:
Private Sub CommandButton1_Click()
End Sub
3) Add the line UserForm1.Show inside of this block of code. This should now look like:
Private Sub CommandButton1_Click()
UserForm1.Show
End Sub
4) Now we will create the userform. On the left side of the editor you will see a section called "Projects - VBA Project", in this list you should see your Workbook. Right click the name of your workbook and click Insert -> UserForm.
5) Use the toolbox to drag the correct components into the Userform. You are free to customize this form as you see fit to add or remove functionality based on your needs. I made mine look like this:
6) In the projects tab you will see your userform named UserForm1. Right click this userform and click "View Code". Paste the following code:
Private Sub CommandButton1_Click()
Unload UserForm1
End Sub
Private Sub UserForm_Initialize()
Dim lastColumn As Long
lastColumn = Worksheets("Sheet1").Cells(1,Columns.Count).End(xlToLeft).Column
For i = 1 To lastColumn
UserForm1.ComboBox1.AddItem (Worksheets("Sheet1").Cells(1, i))
Next
End Sub
Private Sub CommandButton2_Click()
Dim columnName As String
Dim columnIndex As Integer
Dim min As Double
Dim max As Double
If Not (ComboBox1.SelText = "" And TextBox1.Text = "" And TextBox2.Text = "") Then
columnName = ComboBox1.SelText
min = TextBox1.Text
max = TextBox2.Text
Dim lastColumn As Long
lastColumn = Worksheets("Sheet1").Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To lastColumn
If Worksheets("Sheet1").Cells(1, i).Value = columnName Then
columnIndex = i
End If
Next
Dim cellValue As Double
Dim lastRow As Long
lastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
cellValue = Worksheets("Sheet1").Cells(i, columnIndex).Value
' MsgBox CStr(cellValue) + "--" + CStr(cellValue > min) + "--" + CStr(cellValue < max)
If Not (cellValue >= min And cellValue <= max) Then
Worksheets("Sheet1").Cells(i, columnIndex).Value = 0
End If
Next
End If
Unload UserForm1
End Sub
7) Change the component names such as CommandButton, ComboBox1, etc. to match your UserForm.
What does the code do?
Initializing: As soon as the UserForm is called it passes through the method UserForm_Initialize(). This method looks through your WorkSheet and determines the name of all the columns. It then adds these to the ComboBox.
Command Button 1: "Cancel", exits the UserForm without doing anything.
Command Button 2: "Confirm", this method goes to your selected column, checks within the desired range. If a value falls outside that range then it will set it to 0.
I hope this help!!

Excel Userform VBA VLOOKUP from intranet file (2)

Following up from my previous post (of same title). I have a user form from which I need to look up data based on a list of items in a drop down box "XXXXList". The VBA code works partially. The code is able to look for and open the right file from the intranet called "database". But once the file is opened, I get the following error message "Automation error".
The code i have is:
Private Sub ContractsList_AfterUpdate()
Dim WB As Workbook
Dim Sht As Worksheet
' set workbook to workbook location at internet
Set WB = Workbooks.Open("https://Private.Private.Private.uk/Private/Private/Private/Private/Private.xlsm")
Set Sht = WB.Worksheets("Availabledata")
Application.Wait (Now + TimeValue("00:00:01"))
Workbooks("database.xlsm").Close
With Me.XXXXList
'value to be found in Column H of 3rd worhseet
If Not IsError(Application.Match(.Value, Sht.Range("H:H"), 0)) Then
'Lookup values based on first control
Me.TextBox1 = Sht.Range("H" & Application.Match(.Value, Sheet3.Range("H9:H100"), 2)).Value '<-- value not found in Column H
Else
MsgBox "This contract is not on the list"
.Value = ""
Exit Sub
End If
End With
End Sub
Also, the worksheet "database.xlsm" is meant to flash open for a second and then close immediately, but instead it asks me if I want to save the data.
I don't want really want that, is it possible to skip that step and close it automatically?

How do I hide a sheet with a button in Excel?

I would like to create a button to hide the sheet. Ideally, it would hide the sheet where the button is located.
To be simple, sheet 1 has a form to fill out. The typical name, address, phone number, etc. Sheet 2 and 3 also have the same fields that is going to be referenced to the 'Data' tab as well. On a sheet named 'Data', I will add fields that will populate simply with the = option like (=Data!...)
However, I do not want the Data page in view once the information is added. We all know the simple right click and hide sheet. But sometimes that's too much for some people that will use this sheet and a pretty button would work better.
I was successful using:
Module 1
Sub SheetCommand()
If Worksheets("Sheet1").Range("C2").Value <> vbNullString Then
Worksheets("Sheet2").Visible = False
Else
Worksheets("Sheet2").Visible = True
End If
End Sub
Sheet1 Code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address <> "$C$2" Then Exit Sub
Run "SheetCommand"
End Sub
However, I am not very VB savvy and have hit a dead end. Could someone help show me how to apply this to a button? I don't want it to reference the $C$2 field as noted on the example, but just when someone presses the button, the sheet goes away. I'm not worried about getting it back as someone can be ready to get it the old fashioned way. This would help the data entry process for this manual form so much easier.
Edit: basically, I need help creating a vba code where I can hide the page. I'd like to create a button where once clicked, it hides that page. I showed an example of a code where I got it to work but it only works if that cell is populated. How do I make it work on button click?
I found this code that does what I need but I would like to tell it a specific Sheet Name instead of having to type it in B6 and B7.
Sub ShowHideWorksheets()
Dim Cell As Range
For Each Cell In Range("B6:B7")
ActiveWorkbook.Worksheets(Cell.Value).Visible = Not
ActiveWorkbook.Worksheets(Cell.Value).Visible
Next Cell
End Sub
It's actually not very clear to me what's your exact goal
for instance, assuming "Sheet 2" and "Sheet2" would point to the same sheet, in your question you seem to reference it as being both a "Form" sheet ("...sheet 1 has a form to fill out....Sheet 2 and 3 also have the same fields...") and "Data" sheet (Worksheets("Sheet2").Visible = False)
so here follow some possible solutions:
1) you want to hide "Data" sheet before closing the workbook it's contained in
then place the following code in "ThisWorkbook" code pane of the workbook containing "Data" sheet
Private Sub Workbook_BeforeClose(Cancel As Boolean)
ThisWorkbook.Worksheets("Data").Visible = False
End Sub
2) you want to hide "Data" sheet once some cells have been filled up in ANY sheet other than "Data"
then place the following code in "ThisWorkbook" code pane of the workbook containing "Data" sheet
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name <> "Data" Then
With Sh
'here follows code to check if "the information is added"
'for instance:
If WorksheetFunction.CountA(.Range("A2:C2")) = .Range("A2:C2").Count Then ThisWorkbook.Worksheets("Data").Visible = False 'check if all cells in range "A2" to "C2" has been filled with some data
End With
End If
End Sub
3) you want to hide "Data" sheet once some cells have been filled up in ALL sheets other than "Data"
then place the following code in "ThisWorkbook" code pane of the workbook containing "Data" sheet
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim sht As Worksheet
Dim hideBool As Boolean: hideBool = True 'set initial value as true
If Sh.Name <> "Data" Then
For Each sht In ThisWorkbook.Worksheets
With Sh
'here follows code to check if "the information is added"
'for instance:
hideBool = hideBool And WorksheetFunction.CountA(.Range("A2:C2")) = .Range("A2:C2").Count ''check if all cells in range "A2" to "C2" of current sheet has been filled with some data
End With
If Not hideBool Then Exit For
Next sht
ThisWorkbook.Worksheets("Data").Visible = Not hideBool ' hide if ALL sheets met "information is added" condition
End If
End Sub
4) otherwise give more info about the desired behavior