Concatenate string and number as number - vba

I have a text made of some cells with concatenation. One of the items of the text is a number. How to make it a full number with all the necesarry comas etc.
I have: on stt 03/06 db corr PLN 60000000 val 03/06 pending
I need: on stt 03/06 db corr PLN 60,000,000.00 val 03/06 pending
I tried with CDbl(Sheets(1).Cells(i, 5).Value) but the number is still the same.
Please note that the source cell contains the number in correct format : 60,000,000.00 which is downloaded from DB2 database
Many thanks for any help how to achieve that

To concatenate a string and a number you just use &, then convert the result to a number with Val() function.
Then if you want to format the result number you can use Format() function. Then you get a formatted string.
Example:
j = Val("10" & 10)
s = Format(j, "##,###.00")

I think that the use Format Function, resolve your problem -> https://msdn.microsoft.com/en-us/library/office/gg251755.aspx
Maybe format(60000000,"##,##0.00")?

If your cell is already formatted appropriately, you can use its Text property:
Sheets(1).Cells(i, 5).Text
Note that because this is the displayed value, you can get #### returned if the column width is too narrow for the actual value, but it's still useful where you don't necessarily know the format ahead of time.

Related

Exponentiation conversion

I am using:
For t = 1 To ActiveProject.Tasks.Count
With Tasks(t)
' DurSen is a Custom Field Name. It returns an application field Number (such as 188743770 for Number4)
Projectfield = FieldNameToFieldConstant("DurSen")
' the SpearmanRankCorrelation function occasionally produces a result like -6.06060606060606E-03.
.SetField (Projectfield), SpearmanRankCorrelation(ProjectDuration, TmpVec, NN)
End With
Next t
This is a number expressed as an exponent. Due to the presence of the "E" in the number, it fails the Setfield function. The .Setfield places the calculated value into the field referenced by ProjectField for a specific task, (t) but fails when the calculated value contains an "E".
Any ideas on avoiding this problem?
The SetField method expects the Value parameter to be a string. So the solution is to format the number as a string. (e.g. Format(-6.06060606060606E-03, "0.0#####") => -0.006061)
However, Microsoft Project will round the value to the nearest hundredth, so you will lose the precision.
Better to store numbers that require more than two decimal places in a text field and convert them back to numbers as needed in code.
I had a simpler answer hat I figured out yesterday. Instead of trying to deal with it as a number, I simply converted to a string, used the InStr method to see if an "E" was present and if it is, assign a value of 0.001 as the result, as any E value will be smaller than .01.
If InStr(SpearmanRankCorrelation(ProjectDuration, TmpVec, NN), "E") > 0 Then
.SetField (Dursen), 0.001
PD = 0.001
outputstr = ("575 - ID= " & tasks(t).ID & " SpearmanRankCorrelation= " & SpearmanRankCorrelation(ProjectDuration, TmpVec, NN) & " Replaced by 0.001")
Call Txt_Append(myfile, outputstr)
Else
.SetField (Dursen), SpearmanRankCorrelation(ProjectDuration, TmpVec, NN)
End If
Thank you, Rachel, for your answer. I am trying not to use Project Custom fields. The .Setfield above assigns the Result to the field which is identified by the value of Dursen ( which is an internal field reference).
Rachel, I tried your approach but whenever I encountered a result that was expressed with an "E" in the Result, the conversion failed. using >Setfield will only round to the nearest hundreth if the entire string is a numeric value (when converted). The >Setfield method does not work when there is an "E" in the expression.

How to convert Quarter years to other format

I have cells that can either contain time in this format:
1625 (16 for 2016 and 25 for week 25)
Or in this format
2016-Q2 (Q2 means quarter 2 if the year)
When converting I want quarters to be the mid week of the quarter
2016-Q1 = 1608
2016-Q2 = 1620
2016-Q3 = 1633
2016-Q4 = 1646
I dont want to convert the times in the cell its in. I want to convert it to YYWW format for a formula for a timeline in another sheet. So I use help cells with the converted value and reference those instead of the values in the other sheet.
I have done this with nested if functions resulting in mile long formulas because the timeline needs to be very long and the time can very well be 2025-Q3.
a =IF('Gulpilspuls NT'!U4="2016-Q1";1608;IF('Gulpilspuls NT'!U4="2016-Q2";1620;IF('Gulpilspuls NT'!U4="2016-Q3";1633;IF('Gulpilspuls NT'!U4="2016-Q4";1646;IF('Gulpilspuls NT'!U4="2017-Q1";1708;IF('Gulpilspuls NT'!U4="2017-Q2";1720;IF('Gulpilspuls NT'!U4="2017-Q3";1733;IF('Gulpilspuls NT'!U4="2017-Q4";1746;IF('Gulpilspuls NT'!U4="2018-Q1";1808;IF('Gulpilspuls NT'!U4="2018-Q2";1820;IF('Gulpilspuls NT'!U4="2018-Q3";1833;IF('Gulpilspuls NT'!U4="2018-Q4";1846;IF('Gulpilspuls NT'!U4="2019-Q1";1908;IF('Gulpilspuls NT'!U4="2019-Q2";1920;IF('Gulpilspuls NT'!U4="2019-Q3";1933;IF('Gulpilspuls NT'!U4="2019-Q4";1946;IF('Gulpilspuls NT'!U4="2020-Q1";2008;IF('Gulpilspuls NT'!U4="2020-Q2";2020;IF('Gulpilspuls NT'!U4="2020-Q3";2033;IF('Gulpilspuls NT'!U4="2020-Q4";2046;IF('Gulpilspuls NT'!U4="2021-Q1";2108;IF('Gulpilspuls NT'!U4="2021-Q2";2120;IF('Gulpilspuls NT'!U4="2021-Q3";2133;IF('Gulpilspuls NT'!U4="2021-Q4";2146;IF('Gulpilspuls NT'!U4="2022-Q1";2208;IF('Gulpilspuls NT'!U4="2022-Q2";2220;IF('Gulpilspuls NT'!U4="2022-Q3";2233;IF('Gulpilspuls NT'!U4="2022-Q4";2246;IF('Gulpilspuls NT'!U4="2023-Q1";2308;IF('Gulpilspuls NT'!U4="2023-Q2";2320;IF('Gulpilspuls NT'!U4="2023-Q3";2333;IF('Gulpilspuls NT'!U4="2023-Q4";2346;IF('Gulpilspuls NT'!U4="2024-Q1";2408;IF('Gulpilspuls NT'!U4="2024-Q2";2420;IF('Gulpilspuls NT'!U4="2024-Q3";2433;IF('Gulpilspuls NT'!U4="2024-Q4";2446;IF('Gulpilspuls NT'!U4="2025-Q1";2508;IF('Gulpilspuls NT'!U4="2025-Q2";2520;IF('Gulpilspuls NT'!U4="2025-Q3";2533;IF('Gulpilspuls NT'!U4="2025-Q4";2546;IF('Gulpilspuls NT'!U4="2026-Q1";2608;IF('Gulpilspuls NT'!U4="2026-Q2";2620;IF('Gulpilspuls NT'!U4="2026-Q3";2633;IF('Gulpilspuls NT'!U4="2026-Q4";2646;IF('Gulpilspuls NT'!U4="2027-Q1";2708;IF('Gulpilspuls NT'!U4="2027-Q2";2720;IF('Gulpilspuls NT'!U4="2027-Q3";2733;IF('Gulpilspuls NT'!U4="2027-Q4";2746;IF('Gulpilspuls NT'!U4="2028-Q1";2808;IF('Gulpilspuls NT'!U4="2028-Q2";2820;IF('Gulpilspuls NT'!U4="2028-Q3";2833;IF('Gulpilspuls NT'!U4="2028-Q4";2846;IF('Gulpilspuls NT'!U4="2029-Q1";2908;IF('Gulpilspuls NT'!U4="2029-Q2";2920;IF('Gulpilspuls NT'!U4="2029-Q3";2933;IF('Gulpilspuls NT'!U4="2029-Q4";2946;IF('Gulpilspuls NT'!U4="2030-Q1";3008;IF('Gulpilspuls NT'!U4="2030-Q2";3020;IF('Gulpilspuls NT'!U4="2030-Q3";3033;IF('Gulpilspuls NT'!U4="2030-Q4";3046;IF('Gulpilspuls NT'!U4="2031-Q1";3108;IF('Gulpilspuls NT'!U4="2031-Q2";3120;IF('Gulpilspuls NT'!U4="2031-Q3";3146;IF('Gulpilspuls NT'!U4="2031-Q4";3146;IF('Gulpilspuls NT'!U4="2032-Q1";3208;IF('Gulpilspuls NT'!U4="2032-Q2";3220;IF('Gulpilspuls NT'!U4="2032-Q3";3233;IF('Gulpilspuls NT'!U4="2032-Q4";3246;IF('Gulpilspuls NT'!U4="2033-Q1";3308;IF('Gulpilspuls NT'!U4="2033-Q2";3320;IF('Gulpilspuls NT'!U4="2033-Q3";3333;IF('Gulpilspuls NT'!U4="2033-Q4";3346;IF('Gulpilspuls NT'!U4="2034-Q1";3408;IF('Gulpilspuls NT'!U4="2034-Q2";3420;IF('Gulpilspuls NT'!U4="2034-Q3";3433;IF('Gulpilspuls NT'!U4="2034-Q4";3446;IF('Gulpilspuls NT'!U4="2035-Q1";3508;IF('Gulpilspuls NT'!U4="2035-Q2";3520;IF('Gulpilspuls NT'!U4="2035-Q3";3533;IF('Gulpilspuls NT'!U4="2035-Q4";3546;IF('Gulpilspuls NT'!U4="2036-Q1";3608;IF('Gulpilspuls NT'!U4="2036-Q2";3620;IF('Gulpilspuls NT'!U4="2036-Q3";3633;IF('Gulpilspuls NT'!U4="2036-Q4";3646;IF('Gulpilspuls NT'!U4="2037-Q1";3708;IF('Gulpilspuls NT'!U4="2037-Q2";3720;IF('Gulpilspuls NT'!U4="2037-Q3";3733;IF('Gulpilspuls NT'!U4="2037-Q4";3746;IF('Gulpilspuls NT'!U4="2038-Q1";3808;IF('Gulpilspuls NT'!U4="2038-Q2";3820;IF('Gulpilspuls NT'!U4="2038-Q3";3833;IF('Gulpilspuls NT'!U4="2038-Q4";3846;'Gulpilspuls NT'!U4))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
As you can clearly see this method is not the best. I cant make it this long because nested if functions can only contain 64 levels of nesting. Do you guys have a better suggestion for this?
The formula has to work with both formats of time entry and I need it to be able to convert all the cells 1:1 meaning 1 cell in the calendar has to be 1 converted cell in the other spot that I can use for the formula. If the cell in the calendar does not have YYYY-Q1234? it should just show what it is instead as you can see at the end of my formula.
Here is your formula.
=IF(AND(LEN(C6)=4,ISERROR(FIND("-",C6))),C6,MID(C6,3,2)&INDEX({"08",20,33,46},RIGHT(C6,1)))
Make sure there is no excess space in your data. Not like this "2016-Q1 ", but like this "2016-Q1".
EDIT: I just realized that if the original is in the format of YYWW, that you do NOT want it changed to the mid quarter week number. So we simplify the formulas:
=IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
and if you want YYWW to always be rendered as numeric:
=1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46))
And here are the results for various samples:
EDIT: If you need to check for blanks, you can do this simply:
=IF(LEN(A1)=0,"",1*IF(ISNUMBER(-A1),A1,MID(A1,3,2) & CHOOSE(RIGHT(A1,1),"08",20,33,46)))
However, if a 0 will not result in a downstream problem, you can use the original, shorter formula, and merely use a custom format to suppress zero returns: 0;;
And if you need to check for other conditions for which you don't want to process, you can perform similar actions.
something like this should do it, however, mid way through Q1, is week 6, so you'll need to adjust if your year doesn't start at 1/1
Function get_week(strInput As String) As String
Dim strQ As String
Dim bytQ As Byte
Dim dblMultiplier As Double
Dim intWeekNumber As Integer
strQ = Split(strInput, "-")(0)
bytQ = CByte(Right(strQ, 1))
dblMultiplier = (bytQ - 1) / 4
intWeekNumber = (dblMultiplier * 52)
intWeekNumber = intWeekNumber + (13 / 2)
get_week = Split(strInput, "-")(1) & "-" & CStr(intWeekNumber)
End Function
Let me try again
="20"&LEFT(N5,2)&IF(MOD(N5,100)<=8,"-Q1",IF(MOD(N5,100)<=20,"-Q2",IF(MOD(N5,100)<=33,"-Q3",if(MOD(N5,100)<=46,"-Q4","-Q1"))))
Should work for everything past year 2000 ;)

Varying Format "Part Number" sort issue

(Current Sort Sample:)
2-1203-4
2-1206-3
2CM-
3-1610-1
3-999
…
AR3021-A-7802
AR3021-A-7802-1
B43570-
B43570-3
I am working on an 8000+ record parts list. The challenge I am running into is that different manufactures of the parts are using many varying formats for their part numbers. “Part Number” is the field I wish to sort my entire worksheet on. (There are about 10 columns of data in this worksheet.)
My methodology for attacking this challenge was to count the number of characters to the left of any “-“ and count the total number of numeric characters in the field. (I also set “Part Numbers” that started with a non-numeric character to a count value of 99 for both count calculations so those would sort after the numeric values.) From this, I was able to sort on the values to the left of the “-“ using .the MIN of the two counts. (My “Part Numbers” are in Column B and I have a header row which means that my first “Part Number” is in cell B2.)
This method worked up to a point. My challenge is that I need to subsequently sort values after the “-“ character as is illustrated by the erroneous sort of “3-1610-1” being followed by “3-999”
One of the limitations I see is that sorting with  Data  Sort only gives three columns to sort on. To sort on just the characters to the left of the “-“ is costing me those three columns. So, I am unable to repeat the whole process of counting values after the “-“ character and subsequently sorting with  Data  Sort after running the primary sort.
Has the sort of many differing formats of a field such as “Part Number” been solved? Is there a macro that can be applied to this challenge? If so, I would be grateful for your input.
This data is continuously updated with new part numbers so the goal here is to be able to add those additional part numbers to the bottom of the worksheet and use a macro to correctly resort the appended list.
For the record, I am not married to my approach. After all, it didn’t solve my challenge!
Thank you,
Darrell
Place this procedure in a standard code moule:
Public Sub PartNumberSortFormat()
Dim i&, j&, f, vIn, vOut
vIn = [b2:index(b:b,match("*",b:b,-1))]
vOut = vIn
For i = 1 To UBound(vIn)
f = Split(Replace(vIn(i, 1), " ", ""), "-")
For j = 0 To UBound(f)
If IsNumeric(f(j)) Then
f(j) = Format$(f(j), "000000")
Else
f(j) = String$(6 - Len(f(j)), "0") & f(j)
End If
Next
vOut(i, 1) = Join(f, "-")
Next
Columns(1).Insert xlToRight
[a1] = "SORT COLUMN"
[a2].Resize(UBound(vOut)) = vOut
Columns(1).EntireColumn.AutoFit
End Sub
After running the procedure, you will notice that it has inserted a new column A on your worksheet and your data has been scooted over to the right by one column.
This new column A will contain a copy of your part numbers, reformatted in such a fashion to allow normal sorting.
Now select all of the data INCLUDING this new column A and sort A-Z on column A.
After the sort, you may delete the new column A.
This works by padding all characters surrounding dashes to six zeroes.
My Thoughts:
Excel 2010 onwards lets you sort using as many columns as you like. (Not sure about 2007). Don't know which version you have!
You could use the formula SUBSTITUTE to remove all "-" from the part number then sort on the number that remains, which gives you a order more like the one you are wanting.
eg
Value =SUBSTITUTE(B2,"-","")
3-15 315
3-888 3888
3-999 3999
3-1610 31610
3-2610 32610
3-1610-1 316101
3-2610-3 326103
It's not exactly what you need though!
Combine this with other formulas (or a VBA function) to manipulate you part number to be more sortable.
You could use FIND to find the position of the first "-" and extract the numbers before it into one column.
Similarly using FIND, MID and LEN you could extract the numbers between a part number two "-".
I suspect if will be best to write a VBA function to convert a part number into a "sortable value". This might splitting the part number into it's component bits (ie each bit being the text between the "-")
(VBA function split might useful for this. It creates an array.
If you know the formats of ALL the part numbers that can be delivered, you can code accordingly.
I suspect you code will take a numbers like and convert them as shown
AB123-456-78 AB12300456007800
AB12-45-7 AB12000450007000
AB12-45 AB12000450000000
ie padding with zeros each component of the part number
The key to sorting the TEXTUAL values into the order you want is understanding how textuals values get sorted! Do some experiments. Then create zero (or "9") padded numbers that sort the numbers as you required.
I hope this helps.
While not a technical answer to the Excel question, I am a logistician working with extremely large data sets of part numbers - always varying in format. The standard approach used in my field is to "ignore" (remove) special characters from the P/N and append the (clean) P/N to the 5-digit CAGE (manufacturer) code to create a "unique" CAGE + (clean) P/N code for sorting, lookup, etc. Create a column for that construct.

Visual Basic format number to hower many number on left of decimal and 1 decimal without rounding

I am acutally using SSRS but it is for an expression so this is VB code. I am wondering how I would get a number such as 236.4723423 to appear at 236.4 instead of 236.5, so basically I jsut want to truncate it always after 1 decimal.
I tried Format = "N1" this rounds it
I tried Formate = "#######.0" and "######.#" and this rounds it as well.
Any ideas?
value = Math.Floor(value * 10) / 10
Use the format "########.00", then once it's in string form, trim the last char.
Edit:
Dim myString as String
myString = CStr(FORMAT(((SUM(Fields!Shipment_Weight.Value)) / 2000),"######.00"))
myString = myString.Substring(0, myString.Length - 1) & "T"
You will probably want to implement a custom IFormatProvider interface to do this. There is a great example on MSDN here.

Excel: macro to auto-format time (without date)

I'm looking for a simple macro to specify cells as being of type "time" and typing only numbers (for example "955") will format that (and recognise as) "hh:mm" time. In other words, by typing "955", the cell would interpret to "09:55", whereas all I can have it do right now is interpret to "1902-08-12 00:00:00" (most likely 955 is the day number for 1902-08-12).
EDIT:
Part of the need for this is to allow calculation of times post typing (for example, substract two time values to get a timespan, or add several timespans to get a total).
VBA code:
Dim val As String
val = myCell.Value
Dim newval As String
If Len(val) = 2 Then
newval = "00:" & val
ElseIf Len(val) = 3 Then
newval = "0" & Left(val, 1) & ":" & Right(val, 2)
ElseIf Len(val) = 4 Then
newval = Left(val, 2) & ":" & Right(val, 2)
Else
newval = "Not a valid time"
End If
myCell.Value = newval
This code does not detect if the last two digits are a valid time (greater than 59 minutes), but otherwise it should handle most cases.
You'll also need to add a case if someone types in 1 digit, ie. 1 thru 9 minutes after midnight.
If you want it to be formatted as an actual time (date-time type), then change the formatting of the cell to hh:mm.
The value typed in, for example 955, must be manipulated to produce a fraction of a day.
pseudocode:
(left(myCell,len(myCell)-2) + (right(myCell,2)/60)) / 24
This produces the proper decimal value for how much of the day has elapsed and thus will display as a proper 'Time' in the cell with hh:mm formatting.
This isn't the VBA, but a formula that will change the formatting. You could incorporate this into VBA if you wanted to, but should help as a jumping point.
=TIMEVALUE(IF(LEN(A5)=3,"0"&LEFT(A5,1)&":",LEFT(A5,2)&":")&RIGHT(A5,2))
(If A5 is the cell where you enter 955)
(Also, make sure to format the formula cell as your desired time formatting.)
I can help with the code if needed. Just post back.
For some reason Excel does not allow to use ":" in your custom format.
But if you OK with another delimiter, say dash "-", then you can simply create a custom format like this: ##-##
Of course your time has to be in 24 hours format.
Alternatively, you may first enter all your times just like numbers (or better as text if you don't want to lose trailing zeros). And then run your script to insert semicolons between hours and minutes.