Reputation: 135
Hello again and thank you for time !
I have the following code that would not let me work in peace - although I am no VBA power I have managed to put this together in about a week or so. After launching the macro, most of the times I must not touch excel at all for ~2 minutes but I do have occasions for which it closes by itself ...
Sub Filter()
'
' substitute Macro
Application.ScreenUpdating = False
Selection.Copy
ActiveWindow.ActivateNext
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = "buffer"
Dim wsS As Worksheet, wsN As Worksheet, i As Integer, j As Integer, k As Integer, l As Integer
Set wsS = Sheets("buffer")
Set wsN = Sheets("non_confid")
colA = "A"
colB = "B"
colC = "C"
colE = "E"
i = 2
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Selection.Replace What:=" ", Replacement:=","
Range("A1").Copy
Range("z1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Columns("A:y").Select
Range("F25").Activate
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Range("B1").FormulaR1C1 = "=SUBSTITUTE(RC[-1],CHAR(13),"";"")"
Range("C1").FormulaR1C1 = "=SUBSTITUTE(RC[-1],CHAR(10),"";"")"
Range("D1").FormulaR1C1 = "=substitute(rc[-1],""/"","";"")"
Range("e1").FormulaR1C1 = "=substitute(rc[-1],""consultant"","";"")"
Range("f1").FormulaR1C1 = "=substitute(rc[-1],""dessinateur"","";"")"
Range("g1").FormulaR1C1 = "=substitute(rc[-1],""grp"","";"")"
Range("h1").FormulaR1C1 = "=substitute(rc[-1],""projet"","";"")"
Range("i1").FormulaR1C1 = "=substitute(rc[-1],""Inscrire dans ce pavé les projets ou familles concernés"","";"")"
Range("j1").FormulaR1C1 = "=substitute(rc[-1],""Inscrire dans ce pavé les profils demandés"","";"")"
Range("k1").FormulaR1C1 = "=substitute(rc[-1],""Droits en consultation"","";"")"
Range("l1").FormulaR1C1 = "=substitute(rc[-1],""Droits en création"","";"")"
Range("m1").FormulaR1C1 = "=substitute(rc[-1],"":"","";"")"
Range("n1").FormulaR1C1 = "=substitute(rc[-1],""("","";"")"
Range("o1").FormulaR1C1 = "=substitute(rc[-1],"")"","";"")"
Range("p1").FormulaR1C1 = "=substitute(rc[-1],""profil"","";"")"
Range("q1").FormulaR1C1 = "=substitute(rc[-1],""non,confid"","";"")"
Range("r1").FormulaR1C1 = "=substitute(rc[-1],"" "","";"")"
Range("r1").Copy
Range("s2").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Rows("1:1").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Columns("A:r").Select
Selection.Delete Shift:=xlToLeft
Range("A1").Select
Selection.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Tab:=True, Semicolon:=True, Comma:=True, Space:=False, OtherChar:="/", FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array(16, 1), Array(17, 1), Array(18, 1), Array(19, 1), Array(20, 1), Array(21, 1), Array(22, 1), Array(23, 1), Array(24, 1), Array(25, 1), Array(26, 1), Array(27, 1), Array(28, 1), Array(29, 1), Array(30, 1))
Range(Selection, Selection.End(xlToRight)).Copy
Range("A2").PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Rows("1:1").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Columns("A:A").EntireColumn.AutoFit
Rows("1:1").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("a1").FormulaR1C1 = "Sorted"
Range("a1").Select
ActiveSheet.Range("$A$1:$A$300").RemoveDuplicates Columns:=1, Header:=xlNo
ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$a$500"), , xlYes).Name = "Table1"
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:="<>"
Range("B2").Select
ActiveCell.FormulaR1C1 = _
"=IFERROR(IF(ISNA(MATCH([@Sorted],NPDM[Contexte],0)),IF(FIND(""."",[@Sorted]),[@Sorted],""""),""""),"""")"
Range("B1").FormulaR1C1 = "Formula"
Range("Table1[Formula]").Select
Selection.Copy
Range("C2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("B:B").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Range("B1").FormulaR1C1 = "Dot"
Range("Table1[Dot]").Select
Selection.TextToColumns Destination:=Range("Table1[[#Headers],[Dot]]"), _
DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter _
:=True, Tab:=True, Semicolon:=True, Comma:=True, Space:=False, Other _
:=True, OtherChar:=".", FieldInfo:=Array(Array(1, 1), Array(2, 1)), _
TrailingMinusNumbers:=True
Range("C1").FormulaR1C1 = "nDot"
Range("B1").FormulaR1C1 = "Dot"
Range("Table1[Dot]").Select
Selection.Copy
Range("A250").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=True, Transpose:=False
Range("Table1[nDot]").Select
Selection.Copy
Range("A500").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=True, Transpose:=False
Range("B:C").EntireColumn.Delete
For j = 2 To 300
If Not IsEmpty(wsS.Range(colA & j).Value) Then
wsS.Range(colC & i - 1).Value = wsS.Range(colA & j).Value
i = i + 1
End If
Next
Range("A:B").EntireColumn.Delete
For k = 1 To 300
If Not IsEmpty(wsS.Range(colA & k).Value) Then
wsN.Range(colE & i).Value = wsS.Range(colA & k).Value
i = i + 1
End If
Next
Sheets("non_confid").Select
Columns("A:G").EntireColumn.AutoFit
Range("e1").Select
ActiveSheet.ListObjects("Status").Range.AutoFilter Field:=4, Criteria1:="<>"
Range("E2").Select
ActiveWorkbook.Worksheets("non_confid").ListObjects("Status").Sort.SortFields. _
Clear
ActiveWorkbook.Worksheets("non_confid").ListObjects("Status").Sort.SortFields. _
Add Key:=Range("Status[ce ?]"), SortOn:=xlSortOnValues, Order:= _
xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("non_confid").ListObjects("Status").Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("A1").Select
Application.DisplayAlerts = False
Sheets("buffer").Select
ActiveWindow.SelectedSheets.Delete
Application.DisplayAlerts = True
ActiveWorkbook.Saved = True
Application.ScreenUpdating = True
End Sub
PS - since my team mates will be working with this, is there a way for this macro to work on a PC that is in French ? because in an earlier version was not (making "Feuil1" while looking for "Sheet1" and putting formulas in English instead of translating them). As I understood, the macro convert automatically to an universal programming language to be read wherever they are opened.
Upvotes: 0
Views: 769
Reputation: 3310
For non english languages, you could use .FormulaLocal or .FormulaR1C1Local. Developer reference says "Returns or sets the formula for the object, using R1C1-style notation in the language of the user. Read/write Variant".
However, I strongly recommend not using the above, as it will mean it won't work if the macro is run on a different language version. Instead, better practice is to use English in conjunction with .Formula and .FormulaR1C1. This will still open as French in a French version, as Excel automatically displays formulae text in the relevant language.
For example: (I use "FALSE" only as an example - the below is true for formulae too like "=SUM(A1)", and of course, if you really want to set a boolean value then please don't use string "TRUE"!)
ActiveCell.Formula = "FALSE"
Ok - Locale independent - This will be a FALSE boolean value displayed as FALSE in English and displayed as FAUX in French, but in both cases it is a Boolean value
ActiveCell.FormulaLocal = "FAUX"
'Bad - Locale dependent! - This will be a String "FAUX" if the macro is run on an English version, but a boolean FALSE if run on a French version
ActiveCell.Formula = "FAUX"
'Locale independent, but probably not what you want - This will be a String "FAUX" in all languages
You should not hard-code referring to a sheet by something like "Feuil1". This is just a string name, and Excel will not adapt for the User's locale. Instead, when you add a new sheet, immediately assign it to a worksheet variable, then use that.
For example:
'Bad: it might work if the workbook is made on a French version but it won't on English and vice versa
Worksheets("Feuil1").Activate
Worksheets("Sheet1").Activate 'also bad
'Better:
Worksheets(1).Activate
'or
With Worksheets.Add
.Name = "Results"
.Activate
End With
'or (for use outside a With block)
Set resultsWs = Worksheets.Add
As for the rest - I am afraid I do not know what your question is. It is probably crashing sometimes because you are using lots of cut/copy - if it is a very large worksheet or with lots of formulae that recalculate each cut/insert this will take a long time. Unless you need intermediate calculations, disable calculation and screen updating at the start and only re-enable at the end (using Application.ScreenUpdating = False, and Application.Calculation = XLManual)
Upvotes: 3
Reputation: 53623
Cor_Blimey gave you some great information above. I will add to this.
Your code can probably be improved if you learn to avoid the Select
and Activate
methods (which force you to rely on bulkier, cumbersome code that takes longer to execute). It also makes for code that is not as easily legible, because it's not as object-oriented.
Also, many people rely unnecessarily on Copy & Paste
methods, when that can also usually be avoided.
Here is one such example, where you copy a range and then paste values to another range:
Range("A1").Copy
Range("z1").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
This can be simplified like:
Range("Z1").Value = Range("A1").Value
Here is an example of unnecessary Select
method:
Rows("1:1").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
These three lines of code can be replaced with one statement:
Rows("1:1").EntireRow.Delete
And another (there are several examples of such):
Range("B2").Select
ActiveCell.FormulaR1C1 = _
"=IFERROR(IF(ISNA(MATCH([@Sorted],NPDM[Contexte],0)),IF(FIND(""."",[@Sorted]),[@Sorted],""""),""""),"""")"
In the above, you first select/activate a cell, and then you operate on the ActiveCell
. This is unnecessary, you can simply operate on the object directly:
Range("B2").FormulaR1C1 = "=IFERROR(IF(ISNA(MATCH([@Sorted],NPDM[Contexte],0)),IF(FIND(""."",[@Sorted]),[@Sorted],""""),""""),"""")"
THese are some helpful coding practices. Otherwise, @Cor_Blimey's answer above is very good. The Application.ScreenUpdating
should speed up the execution time, and if possible, setting Application.Calculation = xlManual
will also help. However, the .Calculation
method might not be an option in this case, since you may be relying on interim calculations as you're moving .Values
from one range to another.
Upvotes: 3