On another programming related website, I saw this line in someone's signature. This is NOT the first time I've seen such sentiments, although this is the harshest:
"People who work in VB or any variant
thereof are not programmers, they are
circus chimps throwing feces into an
IDE..."
...
Context
I'm working on a little project that consists in a series of Microsoft Excel add-ins (.xlam). The code being submitted for review here, is located in the Reflection project:
Feel free to comment on the project architecture, but I'm mostly interested in the Reflection.LinqEnumerable cl...
@vba4all I think all that's stopping me is that there are no extension methods in VBA. But they are just syntax sugar for static method calls. The LINQ query syntax gets compiled to method calls... ok no IQueryable in VBA... but the real showstopper is deferred execution / lazy evaluation. And the notion of a query provider, so LINQ to Entities can spit out T-SQL. I'm not talking about implementing all of LINQ in VBA...
...but with a Delegate class, most of it can be implemented now. Enumerable.Where was impossible 2 days ago.
@Mat'sMug creating delegates wouldn't be too hard. There would be only two issues. 1 not generating code and just let Application.Run do it's thing. 2. handling the paramerters
I like VBA, I just wish everyone who wrote it had some level of software background rather than being hackers with literally no idea what they are doing
I often compare it to PHP. VBA gets a bad rap because there's a low barrier to entry. A lot of beginners with no frakkin' clue use it. (Although PHP really is a crap language, but that's beside the point.)
There's a lot of people in this room right now that, in my mind, legitimize VB6 as a language.
@RubberDuck the trick is convincing others (I'm happy I found this room, I've never been able to get VBA questions answered on Stack Overflow at this point since 99% of the ones there are "I'm too lazy to use the macro recorder do this for me plz")
Too many crud question. Noise to Signal ratio is too great. And earning any rep there, even with a fantastic answer, is neigh impossible. I know they're just imaginary internet points, but they motivate me.
@RubberDuck I basically said that since using an Optional Parameter `predicate' as Delegate if there shouldn't be a check first using IsMissing(predicate) before checking if it's not nothing.
@Mat'sMug yeah I am still kind of active on SO... I just want to get the 20K rep and then I am pretty much off (unless I spot a really interesting question which will be probably once in a year or two lol )
I don't even bother anymore there, I started choosing to either up/downvote all questions I read there and realized I was downvoting the majority of VBA questions
am doing Outlook automation.The traffic running is MAPI. I need to check whether the MAPI traffic running is encrypted or not. Can you please help me out through VBA ?
I use event handlers in VBA and Outlook frequently. One of them is one which marks any item which is deleted to be marked as read.
Private Sub deletedItems_ItemAdd(ByVal Item As Object)
Application_Startup
On Error Resume Next
Item.UnRead = False
End Sub
Declared via:
Private Wit...
The Aggregate part of your example translates to something roughly like this:
string workingSentence = null;
bool firstElement = true;
foreach (string next in words)
{
if (firstElement)
{
workingSentence = next;
firstElement = false;
}
else
{
workingSe...
Not really a question, but posting this for comments because I don't recall seeing this approach before. I was responding to a comment on a previous answer, and tried something I'd not attempted before: the result was interesting so I though I'd post it as a stand-alone question, along with my o...
Public Function Aggregate(ByVal accumulator As Delegate) As Variant
Dim result As Variant
Dim isFirst As Boolean
Dim value As Variant
For Each value In encapsulated
If isFirst Then
result = value
isFirst = False
Else
result = accumulator.Execute(result, value)
End If
Next
Aggregate = result
End Function
?LinqEnumerable.FromList(List.Create("the", "quick", "brown", "fox")).Aggregate(Delegate.Create("(work,value) => value & "" "" & work"))
fox brown quick the
@Mat'sMug, Here is an issue I have with the Enumerable that I can't work around. It has all of these auxiliary methods that I love but aren't really dependent on the Enumerable. Ideally they would be abstracted to work with anything that implements Get NewEnum
Methods like Aggregate aren't hard to implement outside of Enumerable but once they are required to return a sequence we would like them to return the same type. That I can work around with duck typing as long as the sequence is of the same length.
Public Function SeededAggregate(ByVal seed As Variant, ByVal accumulator As Delegate) As Variant
Dim result As Variant
Dim isFirst As Boolean
isFirst = True
Dim value As Variant
For Each value In encapsulated
If isFirst Then
result = seed
isFirst = False
Else
result = accumulator.Execute(result, value)
End If
Next
SeededAggregate = result
End Function
?LinqEnumerable.FromList(List.Create(4,8,8,3,9,0,7,8,2)).SeededAggregate(0, Delegate.Create("(x,value) => iif(value mod 2 = 0, x + 1, x)"))
5
Also in unrelated news I'm creating a "true/false" table in SQL so I can have a "True/False" selection which allows nulls, since Access blows up with null bit fields
wtf is this madness
Is there a better way to do this? I like to hope there is but I don't think there is..
I hear that Nullable<T> is a C# generic class and it does not work with COM - like any other generic class.
Well, in my C# class library I have:
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("2FCEF713-CD2E-4ACB-A9CE-E57E7F51E72E")]
public interface ICOMClass
{
int? GetNullable();
}...
I'm trying to implement the overloads of .NET's System.Linq.Enumerable.Aggregate in VBA
(yeah, call me nuts - full context here).
This answer was enlightening.
This works...
So I got this version to work as expected:
Public Function Aggregate(ByVal accumulator As Delegate) As Variant
Di...
Public Function SeededAggregate(ByVal seed As Variant, ByVal accumulator As Delegate) As Variant
Dim result As Variant
Dim isFirst As Boolean
isFirst = True
result = seed
Dim value As Variant
For Each value In encapsulated
result = accumulator.Execute(result, value)
Next
SeededAggregate = result
End Function
Public Function SeededAggregate(ByVal seed As Variant, ByVal accumulator As Delegate, Optional ByVal resultSelector As Delegate) As Variant
Dim result As Variant
Dim isFirst As Boolean
isFirst = True
result = seed
Dim value As Variant
For Each value In encapsulated
If resultSelector Is Nothing Then
result = accumulator.Execute(result, value)
Else
result = resultSelector.Execute(accumulator.Execute(result, value))
End If
Next
would it be bad to change the order of the parameters so that I could shove them all under one function?
Decomposition
There are redundancies in translating from Array and Collection.
Consider these three snippits
Dim value As Variant, i As Long 'value is unused?
For i = LBound(values) To UBound(values)
encapsulated.Add values(i)
Next
Dim value As Variant
For Each value In values
r...
@Mat'sMug I never said I liked Optional Parameters. I just dislike ParamArray because a function using it cannot be extended. Application.Run's 30 optional Parameters are worse than ParamArray
oh, not much to see there - I used it in one place, and then refactored and didn't need it anymore; I guess it could be turned into a variable-size indexed thing
Option Explicit
Private Type TTuple
Item1 As Variant
Item2 As Variant
End Type
Private this As TTuple
Public Function Create(ByVal value1 As Variant, ByVal value2 As Variant) As Tuple
Dim result As New Tuple
If IsObject(value1) Then
Set result.Item1 = value1
Else
result.Item1 = value1
End If
If IsObject(value2) Then
Set result.Item2 = value2
Else
result.Item2 = value2
End If
Set Create = result
End Function
Public Property Get Item1() As Variant
In addition to Public and Private, a procedure in an object module can be declared as Friend. A Friend procedure may be called only from within the project that contains the class, regardless of the Instancing property of the class. Suppose Class1 is defined within Project1, and contains the following code:
Public Sub PubSub()
Debug.Print "PubSub"
End Sub
Friend Sub FriendSub()
Debug.Print "FriendSub"
End Sub
Sub NoSub()
Debug.Print "NoSub"
End Sub
Public Function Join(ByVal inner As LinqEnumerable, _
ByVal outerKeySelector As Delegate, _
ByVal innerKeySelector As Delegate, _
ByVal resultSelector As Delegate) As LinqEnumerable
Dim result As New LinqEnumerable
Dim outerValue As Variant
Dim outerKey As Variant
Dim innerValue As Variant
Dim innerKey As Variant
For Each outerValue In encapsulated
outerKey = outerKeySelector.Execute(outerValue)
For Each innerValue In inner
^^ I smell bad performance.. but can't think of a better way
Public Function Intersect(collection2 As Enumerable) As Enumerable 'Collection
On Error GoTo ErrHandler
If collection2 Is Nothing Then
Err.Raise EnumerableInvalidArgumentError, TypeName(Me), InvalidArgumentErrorMessage
End If
Dim results As Enumerable
Set results = New Enumerable
Dim item As Variant
Dim innerItem As Variant
For Each item In mCollection
For Each innerItem In collection2
If item = innerItem And Not IsEmpty(item) Then
If Not results.Contains(innerItem) Then 'curse the lack of shortcircuiting
oh, but I could call ToCollection and remove all matched items as I go...
Dim innerList As System.List
Set innerList = inner.ToList
For Each outerValue In encapsulated
outerKey = outerKeySelector.Execute(outerValue)
For Each innerValue In innerList
innerKey = innerKeySelector.Execute(innerValue)
If outerKey = innerKey Then
result.Add resultSelector.Execute(outer, inner)
innerList.Remove innerValue
End If
Next
Next
I think that just chopped off an exponent :)
now ToList is O(n); Remove is also O(n)
..I'm no big-O expert... does that earn me anything really?
I'm working on a LinqEnumerable class (reviewable here), and I'm no Big-O expert and I'm pretty bad with algorithms, so I wonder what the complexity is for what I've implemented here, and whether it could be improved.
Join
Correlates the elements of two sequences based on matching keys.
My fir...
Public Function Sum(Optional ByVal selector As Delegate) As Double
Dim result As Double
If selector Is Nothing Then
result = Aggregate(Delegate.Create("(total,value) => total+value"))
Else
Dim value As Variant
For Each value In encapsulated
result = result + selector.Execute(value)
Next
End If
Sum = result
End Function
I'm starting to consider tagging with vb.net at this point...
@Mat'sMug Why would it return a variant? Do you really want to muck around trying to figure out what type to return? And worse, trying to figure out what type you're going to get back as a client of the code?
i just need the macro to go down the list of commands I have in my excel sheet.
basically I have a macro made in access that i need repeated per field I have to apply it to.
I was hoping to make a excel macro to make the macros for my access project and save myself alot of typing.
i need this c...
Database program XXX cannot export a query as an Excel file so the people exporting them just select "export as any file ." then type in herp.xls. The program doesn't recognize that format so it prints whatever it decides is the default format.
Sub OpenUnknown(ByVal file_path as String)
If isExcel(file_path) Then
OpenExcel file_path
Else
delim = determineDelimiter(file_path)
If delim = "" Then
OpenFixedWidth file_path, DefaultFixedWidths()
Else
OpenDelimitedFile file_path, delimiter
End If
End If
End Sub
@Mat'sMug lol no! it opens the file as an excel file then reads UnknownWorkbook.fileformat. Then closes the file.
This isn't for Access but for Excel I use this. This is not the greatest nor anybodies preferred solution, but brace yourself.
Public Function IsExcelFormat(ByVal file_path As String) As Boolean
On Error GoTo Nope
Dim wb As Workbook
Application.ScreenUpdating = False
Set wb =...
Can't trust them file extensions. That's just a filename.
You aren't specifying exactly which line of code is causing the error you're getting (look into "VBA Error Handling" if you're having a hard time identifying it), but I believe this:
.clearformating
Is a problem. If it's typed exactly like that in your code, either Microsoft made a typo when t...
> First thing to do, is to find out exactly what instruction is blowing up. When the VBA debug dialog shows up, click the [Debug] button, the illegal instruction should be highlighted in bright yellow.
Create a subroutine to pass the array to by reference.
Private Sub Update(ByRef array as variant, ByVal index as long, ByVal move as long)
For i = index - 1 To ubound(array)
Var_array(i, 1) = Var_array(i + move, 1)
Var_array(i, 2) = Var_array(i + move, 2)
Next i
End Sub
...
You might want to create an account on Code Review, if you want your working code to be peer reviewed - Stack Overflow is typically for broken code, CR makes your code better :) — retailcoder22 secs ago
@RubberDuck
Public Function Sum(Optional ByVal selector As Delegate) As Variant
Dim result As Variant
If selector Is Nothing Then
result = Aggregate(Delegate.Create("(total,value) => total+value"))
Else
Dim value As Variant
For Each value In encapsulated
result = result + selector.Execute(value)
Next
End If
Sum = result
End Function
Public Function Join(ByVal inner As LinqEnumerable, _
ByVal outerKeySelector As Delegate, _
ByVal innerKeySelector As Delegate, _
ByVal resultSelector As Delegate) As LinqEnumerable
Dim result As New LinqEnumerable
Dim innerValue As Variant
Dim innerKey As Variant
Dim innerKeys As New Dictionary
For Each innerValue In inner
Set innerKey = innerKeySelector.Execute(innerValue)
innerKeys.Add innerKey, innerValue
The part that it highlights is the: Selection.Find.Clear Formating 'added your edit I also have this code in a module since i doesn't even give me an error code in the workbook or worksheet objects. — Josiah Cowden10 mins ago
I meant "formating" would be spelled "formatting", with double t's. ClearFormatting ;) — retailcoder24 secs ago
I think I need an AnonymousType class for Join to be usable... the resultSelector would go something like "(employee,emplDept) => new(employee(""JobTitle""),emplDept(""DepartmentID""))" - and then I'd have to ..generate a type on the fly... which I know won't work... ugh.
So I have a Join method that's well implemented, but I don't know how I can test it.
doesn't look too good for GroupBy
@RubberDuck help me out here
:)
oh, how about I pimp up that System.Tuple class
the type I need to return has to be in the System project.
well I'm going to "interpret" the "new()" part of the delegate definition, and "translate" it to "ThatClass.Create(whatever)" - and put that in the generated code
how would I call such a class? AnonymousType is a big fat lie!
or.. why do I need to wrap the dictionary at all? perhaps I could return a dictionary
Okay. So why a dictionary? Why do you need an anonymous type? You already have two LinqEnumerables, you just want to return an Enumerable where some property matches.
in C# you go employees.Join(employeeDepartments, employee => employee.Id, emplDept => emplDept.EmployeeId, (empl, emplDept) => new { Name = empl.Name, Department = emplDept.Name })
and that gives you a bunch of objects with a Name and a Department property