It is alpha code, proof of concept, works for LEFT and RIGHT alignment, center might give problems. Does work with properly formatted D/CSV files (thanks to Rhys & DerRaphael)
before
1,1234,56 12,234,56 112,345,6after
1 ,1234,56 12 ,234 ,56 112,345 ,6this way you can use a text-editor with column mode or the TF_Col* functions
Comments welcome, will probably release an updated TF early 2011 :wink:
file= ( "John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075 John,Doe,120 jefferson st.,Riverside, NJ, 08075 Jack,McGinnis,220 hobo Av.,Phila, PA,09119 Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234 ,Blankman,,SomeTown, SD, 00298 "Joan ""the bone"", Anne",Jet,"9th, at Terrace plc",Desert City,CO,00123 ) FileDelete, TestFile.csv FileAppend, %file%,TestFile.csv _TF_ConvertToFixedColumn("TestFile.csv", ",", 0) ; will create TestFile_copy.csv _TF_ConvertToFixedColumn(Text, Delimiter = "," , Alignment = 0) { ; Alignment = 0 Left ; Alignment = 1 Center ; Alignment = 2 Right Trim:=A_AutoTrim AutoTrim, on TF_GetData(OW, Text, FileName) StringReplace, Text, Text, %A_Tab%, %A_Space%, All ; replace all tabs with spaces just to be sure Loop, Parse, Text, `n, `r { If (A_LoopField = "") Continue Col:=ReturnDSVArray(A_LoopField, "CSV_Row" . A_Index . "_Col", Delimiter) Row:=A_Index } Loop, % Row { ReadRow:=A_Index Loop, % Col { Data:=CSV_Row%ReadRow%_Col%A_Index% Data=%Data% ; autotrim Data:=Format4CSV(Data) Len:=StrLen(Data) If TF_Count(Data,Chr(34)) > 2 ; if Data has " in it substract 2 Len -= 2 If (Len > Longest) Longest:=Len } } Loop, % Row { ReadRow:=A_Index Loop, % Col { Width:=Longest Read:=CSV_Row%ReadRow%_Col%A_Index% Read=%Read% ; autotrim Quotes= Quotes:=TF_Count(Read,Chr(34)) If (Quotes > 0) Width-=2*Quotes Quotes:=TF_Count(Read,Delimiter) If (Quotes > 0) Width-=2*Quotes Read:=SetWidth(Read, Width, Alignment) Read:=Format4CSV(Read) If (StrLen(Read) < Longest) Loop, % Longest - StrLen(Read) Read .= A_Space Output .= Read . Delimiter } StringTrimRight, Output, Output, 1 ; trim trailing Delimiter Output .= "`n" } StringTrimRight, Output, Output, 1 ; trim trailing new line Return TF_ReturnOutPut(OW, OutPut, FileName, TrimTrailing, CreateNewFile) } ; SKAN ; http://www.autohotkey.com/forum/viewtopic.php?p=45880#45880 ; SetWidth() : SetWidth increases a String's length by adding spaces to it and aligns it Left/Center/Right. ( Requires Space() ) SetWidth(Str,Width,AlignText) ; SKAN { If (AlignText!=0 and AlignText!=1 and AlignText!=2) AlignText=0 If AlignText=0 { RetStr= % (Str)Space(Width) StringLeft, RetStr, RetStr, %Width% } If AlignText=1 { Spaces:=(Width-(StrLen(Str))) RetStr= % Space(Round(Spaces/2))(Str)Space(Spaces-(Round(Spaces/2))) } If AlignText=2 { RetStr= % Space(Width)(Str) StringRight, RetStr, RetStr, %Width% } Return RetStr } ; SKAN ; http://www.autohotkey.com/forum/viewtopic.php?p=45880#45880 Space(Width) ; SKAN { Loop,%Width% Space=% Space Chr(32) Return Space } ;### ; Delimiter Seperated Values by DerRaphael ; http://www.autohotkey.com/forum/post-203280.html#203280 ; ; Proof of Concept to extract DSV (Delimiter Seperator Values) ; - adapted for AHK by derRaphael / 21st July 2008 - ; [email protected] ; Following rules apply: ; You have to set a delimiter char and an encapsulation char. ; 1) If you're using the delimeter char within your value, the value has ; to be surrounded by your encapsulation char. One at beginning and one ; at its end. ; 2) If you're using your encapsulation char within your value you have to ; double it each time it occurs and surround your value as in rule 1. ; Remarks: ; The whole concept will break, when using same EOL (End Of Line) as LineBreaks ; in a value as in the entire file. Either you will have to escape these chars ; somehow or use a single linefeed (`n) in values and carriage return linefeed ; (`r`n) as EOL in your DSV file. ; Encapsulation and delimiter chars have to be single Chars. Strings containing ; more than one char are not supported by concept. ;CurrentDSVLine=a,b,c,"d,e","f"","",g",,i ; ;Loop, % ReturnDSVArray(CurrentDSVLine) ; MsgBox % A_Index ": " DSVfield%A_Index% ReturnDSVArray(CurrentDSVLine, ReturnArray="DSVfield", Delimiter=",", Encapsulator="""") { global if ((StrLen(Delimiter)!=1)||(StrLen(Encapsulator)!=1)) { return -1 ; return -1 indicating an error ... } SetFormat,integer,H ; needed for escaping the RegExNeedle properly local d := SubStr(ASC(delimiter)+0,2) ; used as hex notation in the RegExNeedle local e := SubStr(ASC(encapsulator)+0,2) ; used as hex notation in the RegExNeedle SetFormat,integer,D ; no need for Hex values anymore local p0 := 1 ; Start of search at char p0 in DSV Line local fieldCount := 0 ; start off with empty fields. CurrentDSVLine .= delimiter ; Add delimiter, otherwise last field ; won't get recognized Loop { Local RegExNeedle := "\" d "(?=(?:[^\" e "]*\" e "[^\" e "]*\" e ")*(?![^\" e "]*\" e "))" Local p1 := RegExMatch(CurrentDSVLine,RegExNeedle,tmp,p0) ; p1 contains now the position of our current delimitor in a 1-based index fieldCount++ ; add count local field := SubStr(CurrentDSVLine,p0,p1-p0) ; This is the Line you'll have to change if you want different treatment ; otherwise your resulting fields from the DSV data Line will be stored in AHK array if (SubStr(field,1,1)=encapsulator) { ; This is the exception handling for removing any doubled encapsulators and ; leading/trailing encapsulator chars field := RegExReplace(field,"^\" e "|\" e "$") StringReplace,field,field,% encapsulator encapsulator,%encapsulator%, All } Local _field := ReturnArray A_Index ; construct a reference for our ReturnArray name %_field% := field ; dereference _field and assign our value to it if (p1=0) { ; p1 is 0 when no more delimitor chars have been found fieldCount-- ; so correct fieldCount due to last appended delimitor Break ; and exit loop } Else p0 := p1 + 1 ; set the start of our RegEx Search to last result } ; added by one return fieldCount } ;### ; Format4CSV by Rhys ; http://www.autohotkey.com/forum/topic27233.html Format4CSV(F4C_String) { Reformat:=False ;Assume String is OK IfInString, F4C_String,`n ;Check for linefeeds Reformat:=True ;String must be bracketed by double quotes IfInString, F4C_String,`r ;Check for linefeeds Reformat:=True IfInString, F4C_String,`, ;Check for commas Reformat:=True IfInString, F4C_String, `" ;Check for double quotes { Reformat:=True StringReplace, F4C_String, F4C_String, `",`"`", All ;The original double quotes need to be double double quotes } If (Reformat) F4C_String=`"%F4C_String%`" ;If needed, bracket the string in double quotes Return, F4C_String }