duplicate rows

M

Mauro

My worksheet has 7 columns. I need a way to warn the user that the last
inserted data has already been inserted (this if ALL 7 columns are exactely
the same), the same warning should present both entries and then a check box
that, if selected, erases the duplicated row and then, at last, returns to
userform 1 (this to continue with the work). Is it possible to create
something like this in excel?
thanks again
 
D

Dave Peterson

One way to see if all 7 values match is to use an array formula like:

=MATCH(1,((A2:A10="a")*(B2:B10="b")*(C2:C10="C")*(D2:D10="d")*(E2:E10="e")
*(F2:F10="f")*(G2:G10="g")),0)

(You'd hit ctrl-shift-enter instead of just enter)

You could build a userform that accepts input for the 7 columns, then validates
it before you continue.

Debra Dalgleish has a get started with userforms instruction at:
http://www.contextures.com/xlUserForm01.html

I put a simple userform together that had 7 textboxes (textbox1 through
textbox7) and two buttons (ok and cancel).

Then I had a macro like this (in a general module) to show the form:

Option Explicit
Sub testme()
UserForm1.Show
End Sub

Behind the userform, I had this code. Maybe it'll get you started...

Option Explicit
Private Sub CommandButton1_Click()
'cancel button
Unload Me
End Sub
Private Sub CommandButton2_Click()
'ok button
Dim iCtr As Long
Dim ErrorFound As Boolean
Dim DestCell As Range
Dim myFormula As String
Dim LastRow As Long
Dim FirstRow As Long

ErrorFound = False
For iCtr = 1 To 7
With Me.Controls("textbox" & iCtr)
If .Value = "" Then
ErrorFound = True
.SetFocus
Exit For
End If
End With
Next iCtr

If ErrorFound Then
'do nothing
Else
With Worksheets("sheet1")
FirstRow = 2 'headers in row 1??
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

myFormula = ""
For iCtr = 1 To 7
myFormula = myFormula & "*(" & .Range(.Cells(FirstRow, iCtr), _
.Cells(LastRow, iCtr)).Address & "=" & Chr(34) _
& Me.Controls("textbox" & iCtr) & Chr(34) & ")"
Next iCtr
myFormula = Mid(myFormula, 2)
myFormula = "match(1,(" & myFormula & "),0)"
Debug.Print myFormula
If IsError(.Evaluate(myFormula)) Then
'ok to add
Set DestCell = .Cells(LastRow + 1, "A")
For iCtr = 1 To 7
DestCell.Offset(0, iCtr - 1).Value _
= Me.Controls("textbox" & iCtr).Value
Me.Controls("textbox" & iCtr).Value = ""
Next iCtr
Else
MsgBox "already exists, can't add"
End If
End With
End If

End Sub
 
M

Mauro

Hello Dave,
I do have a userform. What I need to do is to have a warning popping out
whenever a "double input" is made. As sometimes a double input is possible,
I need to find a way to show both inputs and then give the operator a
choice: delete or keep and then go back to the input userform. As I work
with people who are not used to computers (yep, they do exist... at least
they do here in Italy) I therefor need to make sure that the only answer
possible is yes/no.

thanks
 
D

Dave Peterson

Well, you could create another user form to show the duplicated values (I don't
see why since it's duplicated, though).

Maybe you could modify this to do more of what you want:

Option Explicit
Private Sub CommandButton1_Click()
'cancel button
Unload Me
End Sub
Private Sub CommandButton2_Click()
'ok button
Dim iCtr As Long
Dim ErrorFound As Boolean
Dim DestCell As Range
Dim myFormula As String
Dim LastRow As Long
Dim FirstRow As Long
Dim Resp As Long
Dim res As Variant

ErrorFound = False
For iCtr = 1 To 7
With Me.Controls("textbox" & iCtr)
If .Value = "" Then
ErrorFound = True
.SetFocus
Exit For
End If
End With
Next iCtr

If ErrorFound Then
'do nothing
Else
With Worksheets("sheet1")
FirstRow = 2 'headers in row 1??
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

myFormula = ""
For iCtr = 1 To 7
myFormula = myFormula & "*(" & .Range(.Cells(FirstRow, iCtr), _
.Cells(LastRow, iCtr)).Address & "=" & Chr(34) _
& Me.Controls("textbox" & iCtr) & Chr(34) & ")"
Next iCtr
myFormula = Mid(myFormula, 2)
myFormula = "match(1,(" & myFormula & "),0)"

Set DestCell = .Cells(LastRow + 1, "A")

res = .Evaluate(myFormula)
If IsError(res) Then
Call AddValuesToSheet(DestCell)
Else
Resp = MsgBox(Prompt:="This record already exists in row: " _
& res + FirstRow - 1 & vbLf & _
"Want to add it anyway?", Buttons:=vbYesNo)
If Resp = vbYes Then
Call AddValuesToSheet(DestCell)
Else
'do nothing else
End If
End If
End With
End If

End Sub
Sub AddValuesToSheet(DestCell As Range)
Dim iCtr As Long
For iCtr = 1 To 7
DestCell.Offset(0, iCtr - 1).Value _
= Me.Controls("textbox" & iCtr).Value
Me.Controls("textbox" & iCtr).Value = ""
Next iCtr
End Sub
Hello Dave,
I do have a userform. What I need to do is to have a warning popping out
whenever a "double input" is made. As sometimes a double input is possible,
I need to find a way to show both inputs and then give the operator a
choice: delete or keep and then go back to the input userform. As I work
with people who are not used to computers (yep, they do exist... at least
they do here in Italy) I therefor need to make sure that the only answer
possible is yes/no.

thanks
<<snipped>>
 
M

Mauro

The program has to do with a ticket office. I need to show the duplicats in
order to avoid
A. double issue of tickets and
B. charging twice the customer's credit card.

As I said in one of my previous posts, I am not a wiz and, I have to admit,
this solution of yours goes far over my capacities... but I would like to
give it a shot... is there a way you can help me (maybe a link or something)
understand the various lines?

thanks for your patience
 
D

Dave Peterson

With comments...

Option Explicit
Private Sub CommandButton1_Click()
'cancel button
'gets rid of the userform
Unload Me
End Sub
Private Sub CommandButton2_Click()
'ok button
'declare some variables
'Long's are integers ..., -3, -2, -1, 0, 1, 2, 3, ...
'booleans are True/False
'ranges are cells or groups of cells on a worksheet
'Variant can hold anything--in this case, it's going to hold a number or
' an error.

Dim iCtr As Long
Dim ErrorFound As Boolean
Dim DestCell As Range
Dim myFormula As String
Dim LastRow As Long
Dim FirstRow As Long
Dim Resp As Long
Dim res As Variant


'check to make sure each of the textboxes has something in them
ErrorFound = False
For iCtr = 1 To 7
With Me.Controls("textbox" & iCtr)
If .Value = "" Then
ErrorFound = True
.SetFocus
Exit For
End If
End With
Next iCtr

If ErrorFound Then
'one of the textboxes is empty, so
'do nothing
Else
'the data has to go somewhere. I chose Sheet1.
With Worksheets("sheet1")
'Avoid row 1 (when checking for duplicates--so start with row 2)
FirstRow = 2 'headers in row 1??
'.end(xlup) is like going to A65536 and hitting the End key
'and then hitting the up arrow to find the last used cell in that
'column
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

'this section tries to build that long formula in the first post
myFormula = ""
For iCtr = 1 To 7
myFormula = myFormula & "*(" & .Range(.Cells(FirstRow, iCtr), _
.Cells(LastRow, iCtr)).Address & "=" & Chr(34) _
& Me.Controls("textbox" & iCtr) & Chr(34) & ")"
Next iCtr
myFormula = Mid(myFormula, 2)
myFormula = "match(1,(" & myFormula & "),0)"

'what cell should get the value from Textbox1.
'find that last used row in column A and come down one row and
'plop it there
Set DestCell = .Cells(LastRow + 1, "A")

res = .Evaluate(myFormula)
If IsError(res) Then
'if that big old formula returns an error, the combination of 7
'entries didn't exist in the worksheet.
'so just call another routine, but tell it where to write the
'values. Since the values could be added if the user has
'duplicated an existing row, it calls a common routine.
Call AddValuesToSheet(DestCell)
Else
'if res is not an error, then it's a duplicate
'find out if the user wants to add it anyway.
Resp = MsgBox(Prompt:="This record already exists in row: " _
& res + FirstRow - 1 & vbLf & _
"Want to add it anyway?", Buttons:=vbYesNo)

If Resp = vbYes Then
'if they clicked the yes button
Call AddValuesToSheet(DestCell)
Else
'do nothing else
End If
End If
End With
End If

End Sub
'this is the common routine
Sub AddValuesToSheet(DestCell As Range)
Dim iCtr As Long
'seven boxes, seven columns, 7 textboxes
For iCtr = 1 To 7
'.offset(x,y) says to go down x, over y
'so .offset(0, ictr-1) says to stay on the same row (0)
'and over 0, 1,2,...,6 columns
DestCell.Offset(0, iCtr - 1).Value _
= Me.Controls("textbox" & iCtr).Value
'and clear the textbox when we're done.
Me.Controls("textbox" & iCtr).Value = ""
Next iCtr
End Sub

Debra Dalgleish has a big list of books for excel at:
http://www.contextures.com/xlbooks.html

John Walkenbach's is a nice one to start with.
 
M

Mauro

Hello Dave,
I've tried to work with the formula you gave me but with no success...
is there a way I can send you my project, to show what is going on? it's
only 650 kb...
thanks

mauro
 
D

Dave Peterson

I don' like opening workbooks.

If you can explain what is wrong in the newsgroup, I think that's better.
(Heck, you'd have to explain it privately anyway.)
 
M

Mauro

Hello Dave, this is the code I have for the "ok" button:

Private Sub cmdNext_Click()
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
Range("A2").Select
ActiveWorkbook.Sheets("Main").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
End Sub

the other button only closes the userform. As you can see I miss cell 5.
This is because cell 5 =SUM(cell7-cell4). (question: is it possible to
create a macro that always subtracts the number in txtTasse from txtTariffa
and puts it in activeCell 0,5 when the ok button is pushed?)....
Now back to the problem:
How can I use your code together with this one? or is this becoming
obsolete?
 
D

Dave Peterson

Basic question first: Is cmdNext the Ok button?

And you could populate the activecell.offset(0,5) with a formula:

activecell.offset(0,5).formulaR1C1 = "=rc[+2]-rc[-1]"
(May have to be adjusted if I counted wrong)

or just plop the value in there:
activecell.offset(0,5).value = cdbl(txttasse.value) - cdbl(txttratta.value)

But I did think that the suggested code could do this--but you'd have to rename
them or populate them like you did in your code:

Sub AddValuesToSheet(DestCell As Range)
destcell.Value = txtData.Value
destCell.Offset(0, 1) = txtPax.Value
destCell.Offset(0, 2) = txtDeparture.Value
destCell.Offset(0, 3) = txtTratta.Value
destcell.offset(0,5).value = cdbl(txttasse.value) - cdbl(txttratta.value)
destCell.Offset(0, 4) = txtTariffa.Value
destCell.Offset(0, 7) = txtTasse.Value
destCell.Offset(0, 6) = txtAgente.Value
End Sub


(I didn't test this--so watch out for typos!)
Hello Dave, this is the code I have for the "ok" button:

Private Sub cmdNext_Click()
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
Range("A2").Select
ActiveWorkbook.Sheets("Main").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
End Sub

the other button only closes the userform. As you can see I miss cell 5.
This is because cell 5 =SUM(cell7-cell4). (question: is it possible to
create a macro that always subtracts the number in txtTasse from txtTariffa
and puts it in activeCell 0,5 when the ok button is pushed?)....
Now back to the problem:
How can I use your code together with this one? or is this becoming
obsolete?
 
M

Mauro

hi Dave,
yes, it is the ok button
Dave Peterson said:
Basic question first: Is cmdNext the Ok button?

And you could populate the activecell.offset(0,5) with a formula:

activecell.offset(0,5).formulaR1C1 = "=rc[+2]-rc[-1]"
(May have to be adjusted if I counted wrong)

or just plop the value in there:
activecell.offset(0,5).value = cdbl(txttasse.value) -
cdbl(txttratta.value)

But I did think that the suggested code could do this--but you'd have to
rename
them or populate them like you did in your code:

Sub AddValuesToSheet(DestCell As Range)
destcell.Value = txtData.Value
destCell.Offset(0, 1) = txtPax.Value
destCell.Offset(0, 2) = txtDeparture.Value
destCell.Offset(0, 3) = txtTratta.Value
destcell.offset(0,5).value = cdbl(txttasse.value) -
cdbl(txttratta.value)
destCell.Offset(0, 4) = txtTariffa.Value
destCell.Offset(0, 7) = txtTasse.Value
destCell.Offset(0, 6) = txtAgente.Value
End Sub


(I didn't test this--so watch out for typos!)
Hello Dave, this is the code I have for the "ok" button:

Private Sub cmdNext_Click()
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
Range("A2").Select
ActiveWorkbook.Sheets("Main").Activate
Range("A2").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
ActiveCell.Value = txtData.Value
ActiveCell.Offset(0, 1) = txtPax.Value
ActiveCell.Offset(0, 2) = txtDeparture.Value
ActiveCell.Offset(0, 3) = txtTratta.Value
ActiveCell.Offset(0, 4) = txtTariffa.Value
ActiveCell.Offset(0, 7) = txtTasse.Value
ActiveCell.Offset(0, 6) = txtAgente.Value
ActiveWorkbook.Sheets("Biglietteria").Activate
Range("A2").Select
End Sub

the other button only closes the userform. As you can see I miss cell 5.
This is because cell 5 =SUM(cell7-cell4). (question: is it possible to
create a macro that always subtracts the number in txtTasse from
txtTariffa
and puts it in activeCell 0,5 when the ok button is pushed?)....
Now back to the problem:
How can I use your code together with this one? or is this becoming
obsolete?
 
M

Mauro

I am checking the rest of your suggestion.
I've added line the following line to the sheet:

ActiveCell.Offset(0, 5).Value = (txtTasse.Value) - (txtTariffa.Value)

and it solved the problem I had with the formula... it created a new
problem, though...

I had this code:

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row < 2 Then Exit Sub
Application.EnableEvents = False
If Target.HasFormula Then
Target.Formula = UCase(Target.Formula)
Else
Target.Value = UCase(Target.Value)
End If
Application.EnableEvents = True
End Sub

which made all cell in capitals... but now that I have no more formulas in
my cells, all the cells are in small letters. I've tried changing it
(erasing the "if target has formula... " til "end if") but with no
success...

About the rest. I am still looking for a way to show the double entry...
 
D

Dave Peterson

I think I'd stop the worksheet_change from firing and capitalize the stuff in
the code that populates the worksheet:

Sub AddValuesToSheet(DestCell As Range)
application.enableevents = false
destcell.Value = txtData.Value
destCell.Offset(0, 1) = Ucase(txtPax.Value)
destCell.Offset(0, 2) = ucase(txtDeparture.Value)
destCell.Offset(0, 3) = txtTratta.Value
destcell.offset(0,5).value = cdbl(txttasse.value) - cdbl(txttratta.value)
destCell.Offset(0, 4) = txtTariffa.Value
destCell.Offset(0, 7) = txtTasse.Value
destCell.Offset(0, 6) = txtAgente.Value
application.enableevents = true
End Sub

Ucase() will make it upper, lcase() will make it lower.

The application.enableevents = false/true will stop the worksheet_change from
firing. (True says that it should go back to looking for those (manual???)
changes.)
 
M

Mauro

Hi Dave.
I've used this code and it works perfectly. I've simply cancelled the code
from the worksheet. this way it won't fire anymore...
By doing what you told me so far my project went from 650 kb down to 160 kb.
I have 2 more problems to solve and then I can take it to the office.... the
first being the double entry one and the second how to save... but I'll get
there later....
 
D

Dave Peterson

Every day is a step closer!
Hi Dave.
I've used this code and it works perfectly. I've simply cancelled the code
from the worksheet. this way it won't fire anymore...
By doing what you told me so far my project went from 650 kb down to 160 kb.
I have 2 more problems to solve and then I can take it to the office.... the
first being the double entry one and the second how to save... but I'll get
there later....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top