Convert DDMMYY to DD-MM-YY in SSIS Derived Column - ssis

I am facing issue while placing "-" in a varchar datatype.
. Need is after last two digits we need to put "-" and then again after two digits and so on.
Input String is- 21220 Output String- 2-12-20
Or,
Input String- 311220 Output String- 31-12-20
Can anyone help me on this ?

I would go with a script component for string manipulation because it's much easier to do and it's more readable.
1) Add a script component as a transformation
2) Under input columns, check your date column (I called this myDate in the example below)
3) Under Inputs and Outputs, under Output 0, add a column for the new date, called formattedDate below
4) In the script, modify the Input0_ProcessInputRow method. Before parsing the string, make sure it's not null. Then pad it with a "0" on the left to insure that we always have a length of 6. Parse, the date elements and set the value for the new column.
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (!Row.mydate_IsNull)
{
var paddedDate = Row.mydate.PadLeft(6, '0');
var day = paddedDate.Substring(0, 2);
var month = paddedDate.Substring(2, 2);
var year = paddedDate.Substring(4, 2);
Row.formattedDate = $"{day}-{month}-{year}";
}
}

(DT_WSTR, 2)(DT_I4)LEFT(RIGHT("0" + #[User::date], 6), 2)
+ "-" + SUBSTRING(RIGHT("0" + #[User::date], 6), 3, 2)
+ "-" + RIGHT(#[User::date] , 2)

Related

Converting cell coordinates without using a column number to column letter method?

I'm trying to figure out what my options are here when I need to use a column number in a formula, and if I really need to write a column number to column letter method to accomplish what I'm trying to do.
See this method I have here:
createFormulas(lookupField, lookupColumns) {
// Iterate through the lookupColumn array
lookupColumns.forEach(value => {
let columnNumber = this.getColumn(this.headers, value);
let range = this.sheet.getRange(2, columnNumber, this.lastRow - 1, 1);
// range.setFormula('=$A2');
range.setFormula('=' + columnNumber + '2' ); // doesn't work obviously
})
}
I'm trying to add formulas in a column based on the column.
this.getColumn() returns the column number based on the column name being passed in.
let range sets the range I want to set the formula in
range.setFormula('=$A2') pastes this formula into range and updates the reference accordingly (i.e., $A3, $A4, etc.). This isn't the formula I ultimately want to use, just a simplified example.
I need to set the column in the reference dynamically, however.
What I have obviously won't work: range.setFormula('=' + columnNumber + '2' );. That would just result in something like 72 where 7 is the column number.
I know I can write a method that will convert the column number into a letter. I'm just surprised there isn't a built in method for doing that or some other native way of accomplishing this.
For example, in Excel VBA I think you can do something like "=" & Cells(2, columnNumber).Address or something like that (been a while, I could be wrong), which should equate to =A2, =A3, =A4, etc. in the range.
So before writing this column number to letter method, I just wanted to check: is that the only way to accomplish what I'm after or is there a native way of handling this that I'm just not seeing?
Actually, was able to do this using .getA1Notation().
Refactored to the following and it works as expected:
createFormulas(lookupField, lookupColumns) {
// Iterate through the lookupColumn array
lookupColumns.forEach(value => {
let columnNumber = this.getColumn(this.headers, value);
let formulaRange = this.sheet.getRange(2, columnNumber, this.lastRow - 1, 1);
let referenceRange = this.sheet.getRange(2, this.idColumn, this.lastRow - 1, 1);
formulaRange.setFormula("=" + referenceRange.getCell(1, 1).getA1Notation());
})
}
Column To Letters
I followed Yuri's path to the numbers to letter functions and I'm a bit baffled that we have forgotten that there are 26 letters in the alphabet and so after looking at the various functions at that reference none of them seem to have worked for me. So here's my replacement:
function colToletters(num) {
let a = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (num < 27) return a[num % a.length];
if (num > 26) {
num--;
let letters = '';
while (num >= 0) {
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[num % 26] + letters;
num = Math.floor(num / 26) - 1;
}
return letters;
}
}
This will calculate the column letters for 1 to 1000 and I check all the way to 703 where the letters go to AAA and they look good all the way.
Just in case. Based on https://stackoverflow.com/a/64456745/14265469
function numberToLetters(num) {
// num--; // if you need 1 --> A, 2 --> B, 26 --> Z
let letters = '';
while (num >= 0) {
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[num % 26] + letters;
num = (num - num % 26) / 26 - 1;
}
return letters;
}
console.log(numberToLetters(0)); // --> A
console.log(numberToLetters(25)); // --> Z
console.log(numberToLetters(26)); // --> AA

Highcharts with external CSV $.get - No xAxis date

I'm trying to create a spline chart using this CSV:
slave_id,date,time,rtc_temp,temp1,temp2,temp3
1,2017/12/26,16:42:59,21,11.50,13.13,5.88
2,2017/12/26,16:43:29,21,14.13,20.63,99.99
1,2017/12/26,16:44:00,21,11.50,13.13,5.88
2,2017/12/26,16:44:30,21,14.13,20.63,99.99
1,2017/12/26,16:45:01,21,11.50,13.13,5.88
2,2017/12/26,16:45:31,21,14.13,20.63,99.99
1,2017/12/26,16:46:02,21,11.50,13.13,5.88
2,2017/12/26,16:46:32,21,14.13,20.63,99.99
As you can see here [IMAGE], the graph is showing the date and time, but the x Axis is not accepting the date / time.
Ive tried using date.UTC, but that did not work either. Can someone point me in the right direction?
https://jsfiddle.net/asvoy6b9/ [not working due to CSV missing]
Full code [Hastebin]
I see that date variable in your code is a string:
// all data lines start with a double quote
line = line.split(',');
date = line[1] + " " + line[2];
(...)
RTC.push([
date,
parseInt(line[3], 10)
]);
If you choose to construct the point's options as an array of two values and the first value is a string then it's treated as its name property (not x).
Explanation: https://www.highcharts.com/docs/chart-concepts/series
In that case Highcharts assigns subsequent integers as x values for all points (that's why there're values like 00:00:00.000 (1 Jan 1970), 00:00:00.001 etc.).
You need to parse your date to timestamp. You can use Date.UTC() (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC) or some other function for this.
I've managed to get it working with Date.UTC using the following code:
var yyyymmdd = line[2].split("-"); //Split the date: 2017 12 16
var hhmmss = line[3].split(":"); //Split the time: 16 11 14
var date = Date.UTC(yyyymmdd[0], yyyymmdd[1] - 1, yyyymmdd[2], hhmmss[0], hhmmss[1], hhmmss[2]); //Stitch 'em together using Date.UTC

AS3 Concatenating Reference Not Working

I'm struggling to concatenate a reference to a variable from a XML document. I'm trying to get:
chat_History.Msg.chatMessage1, chat_History.Msg.chatMessage2, chat_History.Msg.chatMessage3
It's instead over-riding the reference and turning into the value '0', '1', '2'. My code:
public function onReceivedChatData(Event:LoaderEvent)
{
var raw_user_info = LoaderMax.getContent("chatHistory");
var chat_History:XML = XML(raw_user_info);
if (chat_History.Msg)
{
trace("ReceivedChatData");
trace(chat_History);
for (var i:int = 0; i < int(chat_History.chatLength); i++)
{
var chatString:String = chat_History.Msg.chatMessage;
chatString += i.toString();
shopchatbox.shop_chat_window.text = shopchatbox.shop_chat_window.text + "\n" + chatString;
shopchatwidebox.shop_chat_window.text = shopchatwidebox.shop_chat_window.text + "\n" + chatString;
}
}
else
{
trace("chat_History XML Does Not Exist!!! Noooo :( ");
trace(chat_History);
}
}
The chatLength is 3, and it's calling the for statement 3 times correctly, however chatString isn't referencing it's variable (a string) correctly and only appears as '0', '1', '2'. I'm guessing I'm not concatenating this right and that's the problem, but I'm not sure how to do this?
Thanks!
chatString += i.toString();
That's going to give you the indexes 0, 1, 2. i just stores increments for iteration. Not the values from chat_History.Msg.chatMessage So you're adding i onto the content of chatString, not setting the variable name.
var chatString:String = chat_History.Msg.chatMessage;
chatString += i.toString();
Your code here says, take chatString, and set it to the value chat_History.Msg.chatMessage, then concatenate i as a String onto the content of chatString
If you wanted to access your variables by a variable name, I believe you'd do something like this;
var chatString:String = chat_History.Msg["chatMessage"+ String(i+1)];
So i+1 = 1, 2, 3. Which should mean you're accessing chat_History.Msg.chatMessage1, chat_History.Msg.chatMessage2 and chat_History.Msg.chatMessage3
Remove the line;
chatString += i.toString();
I'm afraid I can't test this as I don't have the XML code, but hopefully that gives you a general idea. I'm not 100% sure I've got calling a variable by a variable name correct, but it is possible to call a variable by a string name.
Edit:
After doing a little testing, the syntax appears to be correct, so that should get you the values from chat_History.Msg

ActionScript3 - add thousands separator to negative values

This question relates to an animated map template which we have developed at the UKs Office for National Statistics. It has been applied to many datasets and geographies many uses without problem. For example,
http://www.ons.gov.uk/ons/interactive/vp3-census-map/index.html
http://www.statistica.md/pageview.php?l=ro&idc=390&id=3807
The .fla calls on a supporting .as file (see below) to introduce a thousand separator (in the UK a comma, in Germany a full stop (period) defined elsewhwere.
However, the dataset I am currently mapping has large negative values, and it tutrns out that the ORIGINAL HELPER FUNCTION below does not like negative values with 3, 6, 9 or 12 (etc) digits.
-100 to -999 for instance are rendered NaN,100 to NaN,999.
This is because such values are recognised as being 4 digits long. They are being split, the comma introduced, and the -ve sign is misunderstood.
I reckon the approach must be to use absolute values, add in the comma and then (for the negative values) add the -ve sign back in afterwards. But so far, trials of the ADAPTED HELPER FUNCTION have produced only error. :-(
Can anyone tell me how to put the -ve sign back in , please?
Many thanks.
Bruce Mitchell
==================================================================================
//ORIGINAL HELPER FUNCTION: ACCEPTS A NUMBER AND RETURNS A STRING WITH THOUSANDS SEPARATOR ATTACHED IF NECESSARY
function addThouSep(num) {
/*
a. Acquire the number - 'myTrendValue' or 'myDataValue' - from function calcValues
b. Record it (still as a number) to data precision.
1. Turn dataORtrend into a string
2. See if there is a decimal in it.
3. If there isn't, just run the normal addThouSep.
4. If there is, run addThouSep just on the first bit of the string - then add the decimal back on again at the end.
*/
var myNum:Number = correctFPE(num); // Create number variable myNum and populate it with 'num'
// (myTrendvalue or myData Value from calcValues function) passed thru 'correctPFE'
var strNum:String = myNum+""; // Create string version of the dataORtrend number - so instead of 63, you get '63'
var myArray = strNum.split("."); // Create array representing elements of strNum, split by decimal point.
//trace(myArray.length); // How long is the array?
if (myArray.length==1) { // Integer, no decimal.
if (strNum.length < 4)//999 doesn't need a comma.
return strNum;
return addThouSep(strNum.slice(0, -3))+xmlData.thouSep+strNum.slice(-3);
}
else { // Float, with decimal
if (myArray[0].length < 4)//999 doesn't need a comma
return strNum;
return (addThouSep(myArray[0].slice(0, -3))+xmlData.thouSep+myArray[0].slice(-3)+"."+myArray[1]);
}
}
==================================================================================
//ADAPTED HELPER FUNCTION: ACCEPTS A NUMBER AND RETURNS A STRING WITH THOUSANDS SEPARATOR ATTACHED IF NECESSARY
function addThouSep(num) {
/*
a. Acquire the number - 'myTrendValue' or 'myDataValue' - from function calcValues
b. Record it (still as a number) to data precision.
1. Turn dataORtrend into a string
2. See if there is a decimal in it.
3. If there isn't, just run the normal addThouSep.
4. If there is, run addThouSep just on the first bit of the string - then add the decimal back on again at the end.
*/
var myNum:Number = correctFPE(num); // Create number variable myNum and populate it with 'num'
// (myTrendvalue or myData Value from calcValues function) passed thru 'correctPFE'
var myAbsNum:Number = Math.abs(myNum); // ABSOLUTE value of myNum
var strNum:String = myAbsNum+""; // Create string version of the dataORtrend number - so instead of 63, you get '63'
var myArray = strNum.split("."); // Create array representing elements of strNum, split by decimal point.
//trace(myArray.length); // How long is the array?
if (myNum <0){ // negatives
if (myArray.length==1) { // Integer, no decimal.
if (strNum.length < 4)//999 doesn't need a comma.
return strNum;
return addThouSep(strNum.slice(0, -3))+xmlData.thouSep+strNum.slice(-3);
}
else { // Float, with decimal
if (myArray[0].length < 4)//999 doesn't need a comma
return strNum;
return (addThouSep(myArray[0].slice(0, -3))+xmlData.thouSep+myArray[0].slice(-3)+"."+myArray[1]);
}
}
else // positive
if (myArray.length==1) { // Integer, no decimal.
if (strNum.length < 4)//999 doesn't need a comma.
return strNum;
return addThouSep(strNum.slice(0, -3))+xmlData.thouSep+strNum.slice(-3);
}
else { // Float, with decimal
if (myArray[0].length < 4)//999 doesn't need a comma
return strNum;
return (addThouSep(myArray[0].slice(0, -3))+xmlData.thouSep+myArray[0].slice(-3)+"."+myArray[1]);
}
}
==================================================================================
If you're adding commas often (or need to support numbers with decimals) then you may want a highly optimized utility function and go with straightforward string manipulation:
public static function commaify( input:Number ):String
{
var split:Array = input.toString().split( '.' ),
front:String = split[0],
back:String = ( split.length > 1 ) ? "." + split[1] : null,
pos:int = input < 0 ? 2 : 1,
commas:int = Math.floor( (front.length - pos) / 3 ),
i:int = 1;
for ( ; i <= commas; i++ )
{
pos = front.length - (3 * i + i - 1);
front = front.slice( 0, pos ) + "," + front.slice( pos );
}
if ( back )
return front + back;
else
return front;
}
While less elegant it's stable and performant — you can find a comparison suite at my answer of a similar question https://stackoverflow.com/a/13410560/934195
Why not use something simple like this function I've made?
function numberFormat(input:Number):String
{
var base:String = input.toString();
base = base.split("").reverse().join("");
base = base.replace(/\d{3}(?=\d)/g, "$&,");
return base.split("").reverse().join("");
}
Tests:
trace( numberFormat(-100) ); // -100
trace( numberFormat(5000) ); // 5,000
trace( numberFormat(-85600) ); // -85,600
Explanation:
Convert the input number to a string.
Reverse it.
Use .replace() to find all occurrences of three numbers followed by another number. We use $&, as the replacement, which basically means take all of those occurences and replace it with the value we found, plus a comma.
Reverse the string again and return it.
Did you try using the built in Number formatting options that support localized number values:
Localized Formatting with NumberFormatter

splite string using mutilple characters

what I need is simple thing, I have string which cantains data - time retrived from mySQL in mySQL format HH:MM:SS YY-MM-DD what I need is to split this string in actionscript to array of numbers like this
HH
MM
SS
YY
MM
DD
so I can compare it with current time, any one know how to splite using multiple delimiters at first, then compare it with current time. this is my work until now
var param:Array = datetime.split(" :-");
var currentTime:Date = new Date();
var seconds:uint = currentTime.getSeconds();
var minutes:uint = currentTime.getMinutes();
var hours:uint = currentTime.getHours();
var days:uint = currentTime.getDay();
var monthes:uint = currentTime.getMonth();
var years:uint = currentTime.getFullYear();
if(int(param[3]) > years)
return years + " سنة ";
if(int(param[4]) > monthes)
return monthes + " شهر ";
if(int(param[5]) > days)
return days + " يوم ";
if(int(param[0]) > hours)
return hours + " ساعة ";
if(int(param[1]) > minutes)
return minutes + " دقيقة ";
if(int(param[2]) > seconds)
return seconds + " ثانية ";
return param[0] + " يوم ";
`
Split allows the delimiter to be a regexp, so you can say this or that. Something like this:
myStr.split(/:|-/)
Good luck!
You can use multiple characters, with separated by pipe |
myStr.split(/:|-|[|\(|\)]/)
make sure to use \ if you use ( ) and similar, so ( )
To solve your specific question, you might consider replacing the characters to be the same, and then split on that one. Use datetime.replace(/[ :-]/g, "|") and then split on "|". (I didn't check the correctness of the regexp). What Tyler says is more elegant: datetime.split(/[ -:]/). I stand for the rest though:
What MySQL outputs (via php?) is a standard date notation. You could try and use the Date.parse(dateString) to get a timestamp from it, and convert that into a date object by passing it as the sole constructor parameter:
recordedTime = new Date(Date.parse(datetime));
You could then compare the two date objects directly.
if (recordedTime.getFullYear() > currentTime.getFullYear()) { ... }
Hope it helps.