Note - the document I reference in the title is here:ColumnWidths Property
I have a columnwidths property that I set in code based upon the items in a query for a listbox. This works fine:
colString = "0 in; 2 in; 2 in; 1 in; 0 in;"
Me.lstListbox.ColumnWidths = colString
I have a query which has quite a few columns, 44 to be exact. Two things about what happens when this ColumnWidths property is set for this query:
When I set the ColumnWidths for those 44 columns, so that my colString is "0 in; 2 in; 2 in; 1 in; 0 in;" plus about 39 other column sizes (by inch), I get an error 2176, "The setting for this property is too long." I get it that the string being applied to the property (about 267 chars) is too long, I'm guessing the limit is 255, just no place in the documentation that confirms this.
So, my string is too long to apply to the ColumnWidths property. Looking at the referenced documentation, the default is measured in points, with 72 points being an inch. Or I can specify "0; 144; 144; 72; 0;...etc", which should cut down on the length of the string I use for this property That should be a good substitute. Substituting the following, however, does not work:
colString = "0; 144; 144; 72; 0;"
Me.lstListbox.ColumnWidths = colString
The behavior of the property seems to be incorrect in the VBA documentation. That's one thing.
The other thing - any suggestions on how I can cut the length of the string applied to the property and achieve the same goal - which is set widths in the listbox for the data?
Related
The logic isn't complex. The application uses a temporary table into which data for a report is appended. Once the report has been run, the data is cleared. Initially, the client told me that he would enter all the data (by taking attendance of people attending an event) would be done at once. Now, that has changed. I lookup the max ID in the temp table - if the number of rows is greater than 0. I then want to use dlookup to let the client know where she left off lest they create more problems.
Here's the logic:
Dim VMax As Variant
Dim VNFind As String
VMax = DMax("foodpantryid", "signin_sheet_data") 'This works correctly
MsgBox VMax 'This works correctly
VNFind = DLookup("last_name", "Dat_household_member", "[household_id]" = VMax) 'I get the type mismatch/error 13 here.
MsgBox VNFind 'so this never works
Additional information:
Household_id is a long integer. When I change it to integer, I get an error 94 (invalid use of null).
I have tried setting VMax to variant, integer, and long. Still no success. I would think variant would have worked.
The DLookup works if I don't include "[household_id]" = VMax.
I've tried including the =VMax in "" and that fails as well. That produces a 2471 error.
You've put your = outside the string delimiters.
This means: say your ID is 5. Then the parameter is "[household_id]" = 5. That's a comparison between the string "[household_id]" and the number 5, which causes a type mismatch, because you can't compare strings to numbers unless the string can be cast to a number.
Instead, you should include the = in your string, and the DLookUp should be:
DLookup("last_name", "Dat_household_member", "[household_id] = " & VMax)
Or, better yet, use parameters. This avoids most typecasting and string concatenation errors.
TempVars!VMax = VMax
DLookup("last_name", "Dat_household_member", "[household_id] = TempVars!VMax")
TempVars.Remove "VMax"
I have a variable that can only be set to certain numbers (integers and decimals) and that gets assigned by the user using a property grid. What I want is something that behaves like an Enum, where the users can select from a a drop down list of acceptable values. However enums don't see to support non integer numeric input. Any ideas?
Ended up doing get/set and just changing the value if it's outside the acceptable range.
<DataMember()>
<DisplayName("Fisheye Angle")>
<Description("This value indicates the angle used in the fisheye view, if it is enabled. The acceptable range is 45 to 360 degrees with 180 degrees being the default. ")>
<DefaultValue(180)>
Public Property FisheyeAngle As Double
Get
Return _FisheyeAngle
End Get
Set(value As Double)
If value < 45 Then
_FisheyeAngle = 45
ElseIf value > 360 Then
_FisheyeAngle = 360
Else
_FisheyeAngle = value
End If
End Set
End Property
I'm using the iTextSharp to export reports to PDF and I have a table with all content that I need.
I want to give columns width based on the most wide text of each column, but the GetWidtPoint() method returns text width that I'm not expecting and the column content jumps to the next line.
Below, there is an example about the calculus of the header text width. I put all my table header inside an array first.
Dim ColSize(10) as single
Dim Ck as Chunk
For I = 0 to Colsize.getUpperBound(0)
Ck = new Chunk(Data(I),myFont)
Ck.SetCharacterSpacing(1)
Colsize(I) = Ck.GetWidthPoint
Next I
Finally, the table declaration...
Dim T as new PdfPtable(11)
T.HorizontalAligment = 0
T.WidthPercentage = 100
T.SpacingBefore = 3
T.setWidths(Colsize)
An example about issue:
Through the calculus method that I used, the GetWidthPoint() returns 33 points to "Produto" word, but if i set the column width to 33f so I cant show this text only in the first line. To Show the entire word in the same line, I need to set the column width to 55f.
When i print the text in the cell...
Dim Cell as new PdfpCell(new Phrase(new Chunk(Data(I,X),Font)))
T.addCell(cell)
Any ideas?
Don't forget the cell margins, they are 2 by default, 4 in total. You are not posting the way you are creating the cell but I'm guessing that it's introducing even more margins.
What is the behavior of this function to be when the values being compared are equal?
If
Cell1 = 10
Cell2 = 11
Debug.Print WorksheetFunction.max(Cell1,Cell2)
Will return Cell2. But if
Cell1 = 10
Cell2 = 10
It returns Cell1.
What am I missing here?
UPDATE:
I have a label at Offset(0,-3)
If one value is greater then I get the appropriate label.
When the values are equal I get on label in particular.
Since I have not defined a consequence when the vales are equal, I wonder what I am missing
about the behavior of this function such that it will choose one value over the other when they are equal.
How much more coding should I assume is necessary?
Function testWinner(rng As Range) As String
testWinner = WorksheetFunction.Index(rng, WorksheetFunction.Match(WorksheetFunction.max(rng), rng, 0)).Offset(0, -3)
End Function
It's nothing to do with Max (now that you've edited your question). Max simply returns the value (since they are all the same) and your Match function is looking for an exact match so it scans through the range until it finds the first match then that position is passed to Index.
WorksheetFunction.Max does not return a cell/range. It returns the largest value in a set of value.
By the way: in case of when both values are equal (10,10), the result of Min, Max and Average function will be the same: 10.
If by saying the behaviour of function you mean how it works, it sorts data and gets the highest value. So, in case of set of value: {10, 10, 8}
Max(10,10,8)** = 10
Max.K({10,10,8},2) = 10 'where K = 2, which means the second highest value
Max.K({10,10,8},3) = 8 'where K = 3, which means the third highest value
On the other hand...
row/column A B
1 10 =RANK(A$1:A$3,A1) 'returns 1
2 10 =RANK(A$1:A$3,A2) 'returns 1
3 8 =RANK(A$1:A$3,A3) 'returns 3
Is it more understandable, now?
In your updated example the following happens in your testWinner function:
The Max value is determined: in example one this is 15 (in example 2 it's 14). Note that only the value but not a reference to any cell is returned
The MATCH function searches through through D2:D3 for the value 15 (14). It does so top down and return the first exact match. I.e. in the first example, this results in 1 (in the second example the result is 2)
INDEX will return the 2nd element of D2:D3 (the 1st in the second example), i.e. cell D2 (D3 in ex. 2)
OFFSET returns the cell three to the left
Thus, the answer to your question is not the return of the MAX function - but the MATCH function - which goes top to bottom until it finds the first element matching your criteria, in your case the max.
Independent of this: why do you use a User-Defined-Function for this? If you'd build this with the normal Excel functions, performance would be higher - and non-VBA users could still understand it. Using =INDEX($A$2:$A$3,MATCH(MAX($D$2:$D$3),$D$2:$D$3,0)) you would save the OFFSET - and make it less error prone, as you can now insert columns between A and D without breaking your model!
I am trying to set an orangish color in the following manner:
WorkSheet.Range("A1:A5").Interior.color = 49407
and
WorkSheet.Range("A1:A5").Interior.color = &HC0FF 'Hex value of 49407
Aren't these two supposed to be exactly equivalent?
The colors being set are different.
No, those values are not equivalent: &HC0FF is -16129, whereas &HC0FF& is 49407.
VBA, being a rather old language uses 16 bit integers by default. In this day and age, you pretty much want longs always instead of ints, but you have to ask VBA for them.
&HC0FF is a construct that defines a 16-bit constant from hex. Because the sign bit in this value is set (on, negative) when interpreted as a 16-bit value, hence the conversion to -16129. We may consider that this sucks, but it is not a bug! When you use -16129 (as a signed integer), in 32 bit form, 1's are propagated thru the whole top 16 bits and that results in the blue value of 255.
What you really wanted here is a a 32-bit hex constant: &HC0FF&.
The extra & on the end tells VBA that this is a long constant instead of an int. Interpreted in 32-bits, this is a positive value, so gives the decimal equivalent you're looking for.
In short, ask for long hex constants with the trailing &.
As an aside, this propensity of VBA toward 16 bit can also bite us when using decimal constants, such as in an expression 16000 * 16000, which will overflow 16 bit arithmetic. So, sometimes one needs to use the trailing & on decimal constants too (or assign one to a long first).
This will convert the hex-format colors you have to the RGB Long that Office uses for RGB colors:
Function HexToLongRGB(sHexVal As String) As Long
Dim lRed As Long
Dim lGreen As Long
Dim lBlue As Long
lRed = CLng("&H" & Left$(sHexVal, 2))
lGreen = CLng("&H" & Mid$(sHexVal, 3, 2))
lBlue = CLng("&H" & Right$(sHexVal, 2))
HexToLongRGB = RGB(lRed, lGreen, lBlue)
End Function
I believe the answers from Gimp and Johannes both miss the key issue.
A colour on a computer screen is defined by specifying how much red, blue and green you require. For each of the three colours you specify a number between 0 and 255. These three numbers are normally specified as a single number by concatenating the three separate numbers. With Html you specify a colour as #RRGGBB where RR, GG and BB are hexadecimal numbers or you can replace RRBBGG by the decimal equivalent. With Excel the sequence is reversed so &HBBGGRR or the decimal equivalent.
49407 is the decimal equivalent of 00C0FF which for Excel means Blue = 0, Green = 192 and Red = 255.
But &HC0FF or &H00C0FF is -16129 or Blue = 255, Green = 192 and Red = 255. This seems to be a flaw in the &H conversion. I cannot find anyway of getting C0FF converted to 49407.
If you insist on using the &H conversion, the best I can offer is:
Range("A1:A5").Interior.color = &H01C0FF
This is Blue = 1, Green = 192 and Red = 255 and I cannot tell the difference from Blue = 0, Green = 192 and Red = 255.
But I would recommend:
Range("A1:A5").Interior.color = RGB(255,192,0)
because the RGB function always returns a positive number and you do not have to worry about Excel's reverse sequence.
A Colorcode is usually composed of three values, RED, GREEN, BLUE. Your Hexcode is missing one of the three and excel is autofilling it with FF. So your color C0FF is transformed to be FFC0FF.
Here is an Exampleprogram so you can see it in action, make a new sheet and execute it.
' C0FF will be changed to be FFC0FF
Range("A1").Interior.Color = &HC0FF
Range("A1").Select
ActiveCell.FormulaR1C1 = Range("A1").Interior.Color
Range("A2").Select
ActiveCell.FormulaR1C1 = "=DEC2HEX(R[-1]C,6)"
' 49407 is actually 00C0FF
Range("B1").Interior.Color = 49407
Range("B1").Select
ActiveCell.FormulaR1C1 = Range("B1").Interior.Color
Range("B2").Select
ActiveCell.FormulaR1C1 = "=DEC2HEX(R[-1]C,6)"
' Use RGB to have better control over your results
' Switch the order when doing so: 00C0FF => 00 Blue C0 Green FF Red
Range("C1").Interior.Color = RGB(&HFF, &HC0, &H0)
Range("C1").Select
ActiveCell.FormulaR1C1 = Range("C1").Interior.Color
Range("C2").Select
ActiveCell.FormulaR1C1 = "=DEC2HEX(R[-1]C,6)"
EDIT: Added a third example to illustrate switching the colors as suggested in a different answer.