線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3431
推到 Plurk!
推到 Facebook!

如何將文字檔排序後,輸出產生一個新的文字檔

答題得分者是:jow
yjs
一般會員


發表:2
回覆:6
積分:1
註冊:2009-11-23

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-11-23 13:02:09 IP:59.125.xxx.xxx 訂閱
原使檔案內容如下 *.txt
2009/11/13 00:02:31,,0026631039,01,1520000015,張三三,業務部,g12343233
2009/11/13 01:01:50,,0108943087,01,1509000012,李四四,管理部,K23123456
2009/11/13 01:01:52,,0009447233,01,1509000014,王五五,廠務部,l123456787



經過處理排序後輸出檔*.txt(排序依據號工編號)
日期 時間 卡號 員工編號
2009/11/13 01:01:58,00,0108943087,01,00,0009447233,01,00,0026631039,01,00

小弟試過很多方法,但一直弄不出來

煩請知道的人指導一下!!



syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-11-24 08:17:02 IP:59.125.xxx.xxx 訂閱
我想,這沒有很難喔 (會寫程式,懂排序法,十個九個會喔) ~ 腦筋轉一轉

首先假設,你的資料一行為單位,中間沒有分行符號,如果不是這樣,請自行調整程式,或是資料

以一行為依據讀入存成 TStringList

將要排序的欄位找出,以 tag 或是 Object 的方式附加在 TStringList 上
再使用一個 TList,採用類似選擇排序法的方式,挑出最小值,放到 TList 內 (放的是 TStringList,而不是其 Tag / Object)

這樣有沒有會錯意??

===================引 用 yjs 文 章===================
原使檔案內容如下 *.txt
2009/11/13 00:02:31,,0026631039,01,1520000015,張三三,業務部,g12343233
2009/11/13 01:01:50,,0108943087,01,1509000012,李四四,管理部,K23123456
2009/11/13 01:01:52,,0009447233,01,1509000014,王五五,廠務部,l123456787



經過處理排序後輸出檔*.txt(排序依據號工編號)
日期 時間 卡號 員工編號
2009/11/13 01:01:58,00,0108943087,01,00,0009447233,01,00,0026631039,01,00

小弟試過很多方法,但一直弄不出來

煩請知道的人指導一下!!



christie
資深會員


發表:30
回覆:299
積分:475
註冊:2005-03-25

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-11-24 10:25:38 IP:59.125.xxx.xxx 未訂閱
參考參考
以TList為例,
unit TList_U;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
// The customer class definition
TCustomer = class
private
// The data fields of this new class
CustomerName : String;
CustomerNumber : Integer;
public
// Properties to read these data values
property Name : String
read CustomerName;
property Number : Integer
read CustomerNumber;
// Constructor
constructor Create(const CustomerName : String;
const CustomerNumber : Integer);
end;
// The form class definition
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
// The TList object we use in this code
myList : TList;
// Method to show the contents of our list object
procedure ShowListContents;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// Customer constructor
// --------------------------------------------------------------------------
constructor TCustomer.Create(const CustomerName : String;
const CustomerNumber : Integer);
begin
// Save the passed parameters
self.CustomerName := CustomerName;
self.CustomerNumber := CustomerNumber;
end;

// TList sort routine : compare customers by name
// --------------------------------------------------------------------------
// The returned integer has the following value :
//
// > 0 : (positive) Item1 is less than Item2
// 0 : Item1 is equal to Item2
// < 0 : (negative) Item1 is greater than Item2
function compareByName(Item1 : Pointer; Item2 : Pointer) : Integer;
var
customer1, customer2 : TCustomer;
begin
// We start by viewing the object pointers as TCustomer objects
customer1 := TCustomer(Item1);
customer2 := TCustomer(Item2);
// Now compare by string
if customer1.Name > customer2.Name
then Result := 1
else if customer1.Name = customer2.Name
then Result := 0
else Result := -1;
end;

function compareByVal(Item1 : Pointer; Item2 : Pointer) : Integer;
var
customer1, customer2 : TCustomer;
begin
// We start by viewing the object pointers as TCustomer objects
customer1 := TCustomer(Item1);
customer2 := TCustomer(Item2);
// Now compare by Number
if customer1.Number > customer2.Number
then Result := 1
else if customer1.Number = customer2.Number
then Result := 0
else Result := -1;
end;
// A routine to display the contents of our list
// --------------------------------------------------------------------------
procedure TForm1.ShowListContents;
var
i : Integer;
begin
// And redisplay the list
for i := 0 to myList.Count-1 do
begin
ShowMessage(TCustomer(myList[i]).Name ' is customer number '
IntToStr(TCustomer(myList[i]).Number));
end;
end;
// Form constructor
// --------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
var
customer : TCustomer;
begin
// Create the TList object to hold a set of customer objects
myList := TList.Create;
// Create some customer objects and add to our object list
customer := TCustomer.Create('Neil Moffatt', 1509000123);
myList.Add(customer);
customer := TCustomer.Create('Bill Gates', 1509000064);
myList.Add(customer);
// We can add the object without assigning to an intermediate variable
myList.Add(TCustomer.Create('Henry Cooper', 1520000999));
myList.Add(TCustomer.Create('Alan Sugar', 1520000012));
// Now display the list
ShowListContents;
// We will now sort the list into val. sequence and redisplay
ShowMessage('Sorted by Val.');
myList.Sort(compareByVal);
// And redisplay the list
ShowListContents;
// Now do some object inserts and deletes
// Note that indices start at 0
//myList.Insert(2, TCustomer.Create('Added as item 3', 33));
//myList.Delete(4);
// And redisplay the list
//ShowListContents;
// Free up the list
myList.free
end;
end.
------
What do we live for if not to make life less difficult for each other?
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-11-25 09:06:58 IP:211.74.xxx.xxx 未訂閱

[code delphi]
unit fMain;

interface

uses
Windows, Classes, Controls, SysUtils, Forms, StdCtrls;

const
FIELD_COUNT = 9;

type

TArrayOfString = array of string;

TRec = class(TObject)
private
FFields: TArrayOfString;
public
constructor Create(const A: TArrayOfString);
destructor Destroy; override;
class function ToFields(const S: string; var A: TArrayOfString): Boolean;
class function ToString(const A: TArrayOfString): string;
end;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TRec }

constructor TRec.Create(const A: TArrayOfString);
var
I: Integer;
begin
inherited Create;
SetLength(FFields,Length(A));
for I := 0 to Length(A)-1 do FFields[I] := A[I];
end;

destructor TRec.Destroy;
begin
FFields := nil;
inherited;
end;

class function TRec.ToFields(const S: string; var A: TArrayOfString): Boolean;
var
I: Integer;
L: TStringList;
begin
A := nil;
if S <> '' then
begin
L := TStringList.Create;
try
L.CommaText := S;
if L.Count = FIELD_COUNT then
begin
SetLength(A,L.Count);
for I := 0 to L.Count-1 do
begin
A[I] := L[I];

if A[I] = '' then
case I of
2: A[I] := '00';
end;

end;
end;
finally
FreeAndNil(L);
end;
end;
Result := Length(A) = FIELD_COUNT;
end;

class function TRec.ToString(const A: TArrayOfString): string;
var
I: Integer;
L: TStringList;
begin
Result := '';
if Length(A) = FIELD_COUNT then
begin
L := TStringList.Create;
try
for I := 0 to Length(A)-1 do
L.Add(A[I]);
Result := L.CommaText;
finally
FreeAndNil(L);
end;
end;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
const
SrcFileName = 'C:\TEST.TXT';
DestFileName= 'C:\RESULT.TXT';
var
I: Integer;
X,L: TStringList;
A: TArrayOfString;
r: TRec;
begin
X := TStringList.Create;
try

X.Sorted := True;
X.Duplicates := dupIgnore;

if FileExists(SrcFileName) then
begin
L := TStringList.Create;
try
L.LoadFromFile(SrcFileName);
for I := 0 to L.Count-1 do
begin
if TRec.ToFields(L[I],A) then
begin
r := TRec.Create(A);
X.AddObject(A[5],r);
end;
end;
finally
FreeAndNil(L);
end;

L := TStringList.Create;
try
for I := 0 to X.Count-1 do
begin
r := TRec(X.Objects[I]);
L.Add(r.ToString(r.FFields));
end;
L.SaveToFile(DestFileName);
ShowMessage(L.Text);
finally
FreeAndNil(L);
end;

end;
finally
for I := 0 to X.Count-1 do
X.Objects[I].Free;
FreeAndNil(X);
end;
end;

end.
[/code]

謹供參考...^_^
編輯記錄
jow 重新編輯於 2009-11-25 09:08:36, 註解 無‧
yjs
一般會員


發表:2
回覆:6
積分:1
註冊:2009-11-23

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-11-25 10:40:36 IP:59.125.xxx.xxx 訂閱
非常感謝!
但試著執行後發現資料經過轉換後會少掉一半
原始資料
2009/11/12 07:58:02,,0108943078,00,1230000002,許永杰,資訊中心,L12540389




jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-11-25 11:02:36 IP:211.74.xxx.xxx 未訂閱

X.Sorted := True;
X.Duplicates := 2009/11/12 17:18:48,,0108943078,01,1230000002,許永杰,資訊中心,L12540389

就是會少掉下班的記錄,只剩上班的記錄

還在了解你的程式中!!!






yjs
一般會員


發表:2
回覆:6
積分:1
註冊:2009-11-23

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-11-25 12:01:53 IP:59.125.xxx.xxx 訂閱

[code delphi]
請在此區域輸入程式碼
[/code]
unit Unit1;
interface
uses
Windows, Classes, Controls, SysUtils, Forms, StdCtrls, Dialogs;
const
FIELD_COUNT = 9;
type
TArrayOfString = array of string;
TRec = class(TObject)
private
FFields: TArrayOfString;
public
constructor Create(const A: TArrayOfString);
destructor Destroy; override;
class function ToFields(const S: string; var A: TArrayOfString): Boolean;
class function ToString(const A: TArrayOfString): string;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
OpenDialog1: TOpenDialog;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TRec }
constructor TRec.Create(const A: TArrayOfString);
var
I: Integer;
begin
inherited Create;
SetLength(FFields,Length(A));
for I := 0 to Length(A)-1 do FFields[I] := A[I];
end;
destructor TRec.Destroy;
begin
FFields := nil;
inherited;
end;
class function TRec.ToFields(const S: string; var A: TArrayOfString): Boolean;
var
I: Integer;
L: TStringList;
begin
A := nil;
if S <> '' then
begin
L := TStringList.Create;
try
L.CommaText := S;
if L.Count = FIELD_COUNT then
begin
SetLength(A,L.Count);
for I := 0 to L.Count-1 do
begin
A[I] := L[I];
if A[I] = '' then
case I of
2: A[I] := '00';
end;
end;
end;
finally
FreeAndNil(L);
end;
end;
Result := Length(A) = FIELD_COUNT;
end;
class function TRec.ToString(const A: TArrayOfString): string;
var
I: Integer;
L: TStringList;
begin
Result := '';
if Length(A) = FIELD_COUNT then
begin
L := TStringList.Create;
try
for I := 0 to Length(A)-1 do
L.Add(A[I]);
Result := L.CommaText;
finally
FreeAndNil(L);
end;
end;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
const
SrcFileName = 's'; //設定SrcFileName等於剛剛Button2載入的檔名
DestFileName= 'C:\RESULT.TXT';
var
I: Integer;
X,L: TStringList;
A: TArrayOfString;
r: TRec;
begin
X := TStringList.Create;
try
X.Sorted := True;
X.Duplicates := dupAccept;
if FileExists(SrcFileName) then
begin
L := TStringList.Create;
try
L.LoadFromFile(SrcFileName);
for I := 0 to L.Count-1 do
begin
if TRec.ToFields(L[I],A) then
begin
r := TRec.Create(A);
X.AddObject(A[5],r);
end;
end;
finally
FreeAndNil(L);
end;
L := TStringList.Create;
try
for I := 0 to X.Count-1 do
begin
r := TRec(X.Objects[I]);
L.Add(r.ToString(r.FFields));
end;
L.SaveToFile(DestFileName);
// ShowMessage(L.Text);
finally
FreeAndNil(L);
end;
end;
finally
for I := 0 to X.Count-1 do
X.Objects[I].Free;
FreeAndNil(X);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
S : string;
begin
if OpenDialog1.Execute then // 利用開啟方式打開*.txt
S:=Opendialog1.FileName; //設定變數 S 來原檔名
Edit1.text:=S; //顯示檔案路徑
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
end.

不好意思!麻煩你了!可以再問一下嗎?
我想把程式改寫成用 Opendialog1 元件來載入檔案,並 將轉換後結果再用Savedialog1選擇儲存位置
上面是我修改你的程式,但好想執行上面程式,沒有輸出結果!
可以再幫我看看嗎?

jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-11-25 13:34:08 IP:211.74.xxx.xxx 未訂閱

[code delphi]
unit fMain;

interface

uses
Windows, Classes, Dialogs, Controls, SysUtils, Forms, StdCtrls;

const
FIELD_COUNT = 9;

type

TArrayOfString = array of string;

TRec = class(TObject)
private
function GetFFields(Index: Integer): string;
procedure SetFields(Index: Integer; const Value: string);
protected
FFields: TArrayOfString;
public
constructor Create(const A: TArrayOfString);
destructor Destroy; override;
class function ToFields(const S: string; var A: TArrayOfString): Boolean;
class function ToString(const A: TArrayOfString): string;
property Fields[Index: Integer]: string read GetFFields write SetFields;
end;

TRecList = class(TObject)
private
FSortType: Integer;
function GetCount: Integer;
function GetRec(Index: Integer): TRec;
function GetSortedRec(Index: Integer): TRec;
procedure DoSort(SortType: Integer);
procedure SetSortType(const Value: Integer);
protected
FList: TStringList;
FSortList: TStringList;
procedure ClearList;
procedure LoadFromFile(const SrcFileName: string);
procedure SaveToFile(SortType: Integer; const DestFileName: string);
property Count: Integer read GetCount;
property Rec[Index: Integer]: TRec read GetRec;
public
constructor Create(FileName: string);
destructor Destroy; override;
property SortType: Integer read FSortType write SetSortType;
property SortedRec[Index: Integer]: TRec read GetSortedRec;
end;

TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TRec }

constructor TRec.Create(const A: TArrayOfString);
var
I: Integer;
begin
inherited Create;
SetLength(FFields,Length(A));
for I := 0 to Length(A)-1 do FFields[I] := A[I];
end;

destructor TRec.Destroy;
begin
FFields := nil;
inherited;
end;

function TRec.GetFFields(Index: Integer): string;
begin
if (Index>-1) and (Index then Result := FFields[Index]
else Result := '';
end;

procedure TRec.SetFields(Index: Integer; const Value: string);
begin
if (Index>-1) and (Indexend;

class function TRec.ToFields(const S: string; var A: TArrayOfString): Boolean;
var
I: Integer;
L: TStringList;
begin
A := nil;
if S <> '' then
begin
L := TStringList.Create;
try
L.CommaText := S;
if L.Count = FIELD_COUNT then
begin
SetLength(A,L.Count);
for I := 0 to L.Count-1 do
begin
A[I] := L[I];
if A[I] = '' then
case I of
2: A[I] := '00';
end;
end;
end;
finally
FreeAndNil(L);
end;
end;
Result := Length(A) = FIELD_COUNT;
end;

class function TRec.ToString(const A: TArrayOfString): string;
var
I: Integer;
L: TStringList;
begin
Result := '';
if Length(A) = FIELD_COUNT then
begin
L := TStringList.Create;
try
for I := 0 to Length(A)-1 do
L.Add(A[I]);
Result := L.CommaText;
finally
FreeAndNil(L);
end;
end;
end;

{ TRecList }

procedure TRecList.ClearList;
var
I: Integer;
begin
for I := 0 to FList.Count-1 do
FList.Objects[I].Free;
end;

constructor TRecList.Create(FileName: string);
begin
inherited Create;
FList := TStringList.Create;
FList.Sorted := False;//不排序,維持原資料順序
FSortList := nil;
LoadFromFile(FileName);
SetSortType(1);
end;

destructor TRecList.Destroy;
begin
ClearList;
FreeAndNil(FList);
FreeAndNil(FSortList);
inherited;
end;

function TRecList.GetCount: Integer;
begin
Result := FList.Count;
end;

function TRecList.GetRec(Index: Integer): TRec;
begin
if (Index>-1) and (Index then Result := TRec(FList.Objects[Index])
else Result := nil;
end;

procedure TRecList.LoadFromFile(const SrcFileName: string);
var
I: Integer;
L: TStringList;
A: TArrayOfString;
r: TRec;
begin
if FileExists(SrcFileName) then
begin
L := TStringList.Create;
try
L.LoadFromFile(SrcFileName);
for I := 0 to L.Count-1 do
begin
if TRec.ToFields(L[I],A) then
begin
r := TRec.Create(A);
FList.AddObject('',r);//不排序
end;
end;
finally
FreeAndNil(L);
end;
end;
end;

procedure TRecList.SetSortType(const Value: Integer);
begin
if FSortType <> Value then
begin
FSortType := Value;
DoSort(FSortType);
end;
end;

procedure TRecList.DoSort(SortType: Integer);
var
I: Integer;
Key: string;
r: TRec;
begin
if FSortList = nil then
begin
FSortList := TStringList.Create;
FSortList.Sorted := True;
FSortList.Duplicates := dupAccept;
end;

FSortList.Clear;
for I := 0 to FList.Count-1 do
begin
r := TRec(FList.Objects[I]);

//Define SortKey Here.
case SortType of
1: Key := r.Fields[5];
2: Key := r.Fields[5] r.Fields[4];
else Key := TRec.ToString(r.FFields);
end;
//Define SortKey Here.

FSortList.AddObject(Key,r);
end;

end;

function TRecList.GetSortedRec(Index: Integer): TRec;
begin
if (Index>-1) and (Index then Result := TRec(FSortList.Objects[Index])
else Result := nil;
end;

procedure TRecList.SaveToFile(SortType: Integer; const DestFileName: string);
var
I: Integer;
L: TStringList;
r: TRec;
begin
SetSortType(SortType);
L := TStringList.Create;
try
for I := 0 to FSortList.Count-1 do
begin
r := SortedRec[I];
L.Add(r.ToString(r.FFields));
end;
L.SaveToFile(DestFileName);
ShowMessage(L.Text);
finally
FreeAndNil(L);
end;
end;

{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
const
RS_CONFIRMATION =
'Destination file already Exists,'
#$D#$A
'Do you want to overwrite it?';
var
bool: Boolean;
RecList: TRecList;
begin
if OpenDialog1.Execute then
begin
RecList := TRecList.Create(OpenDialog1.FileName);
try
if SaveDialog1.Execute then
begin
bool := False;
if not FileExists(SaveDialog1.FileName)then bool := True
else if MessageDlg(RS_CONFIRMATION,mtConfirmation,[mbYes,mbNo],0) = mrYes then bool := True;
if bool then RecList.SaveToFile(1,SaveDialog1.FileName);
end;
finally
FreeAndNil(RecList);
end;
end;
end;

end.
[/code]


新增TRecList
謹供參考

編輯記錄
jow 重新編輯於 2009-11-25 13:41:08, 註解 無‧
yjs
一般會員


發表:2
回覆:6
積分:1
註冊:2009-11-23

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-11-25 15:30:24 IP:59.125.xxx.xxx 訂閱
非常感謝!終於把問題解決了!!
系統時間:2024-03-29 0:51:20
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!