有許多單機版的進銷存系統、餐飲POS系統或是會計系統,會使用SQL SERVER EXPRESS的版本,然後連線字串變成了 LOCALHOST\SQLEXPRESS。
在安裝後預設是會多了一個\SQLEXPRESS
那如果是安裝正式版本的話,怎麼辦呢?
到SQL SERVER的組態管理員裡面
新增別名,伺服器指到本機 (local),然後別名名稱設為 localhost\sqlexpress 就可以了!
大型網站架構..net 架構師.rabbitMQ.redis.行動開發.APP開發教學.PHP Laravel開發..net core C# 開發.架構師之路.Delphi開發.資料庫程式.進銷存.餐飲POS系統
POS(Point Of Sales)收銀點餐、餐飲、進銷存、門市管理系統開發
在國外行之有年的取餐呼叫器(Pager)最近也在台灣風行起來,看到了二款取餐呼叫器,一個是國產亞克高科(ARCT)由銥特爾科技(02-29974000)代理,一個是韓國(Syscall)製造由鋐鈦科技代理。
二款都可以透過COM PORT設定~~ 以Delphi以及C#針對韓國的做範例。
Delphi
var iPagerno :Integer;
sStr,s :AnsiString;
begin
Try
Pager_COM.StopComm; // 先將Pager Com關閉
Pager_COM.CommName := ComName;
Pager_COM.StartComm;
Sleep(50); //開啟COM需等待
iPagerno := StrToIntDef(PagerNo,1);
sStr := copy(IntToStr(iPagerno),1,4)
s:= Ansichar(#開始指令)+sStr+Ansichar(#結束指令);
Pager_COM.WriteCommData(PAnsiChar(s),Length(s));
Except
End;
C#
public void Pager_Send(String COMName,String PagerNo)
{
public static System.IO.Ports.SerialPort PAGERPORT = new System.IO.Ports.SerialPort();
byte[] PAGERSTART = { 開始指令 };
byte[] PAGEREND = { 結束指令 };
try
{
if (PAGERPORT.IsOpen)
PAGERPORT.Close();
PAGERPORT.PortName = COMName;
PAGERPORT.BaudRate = 9600;
PAGERPORT.Parity = System.IO.Ports.Parity.None;
PAGERPORT.DataBits = 8;
PAGERPORT.StopBits = System.IO.Ports.StopBits.One;
PAGERPORT.Open();
if (!PAGERPORT.IsOpen)
PAGERPORT.Open();
for (int i = 0; i < PAGERSTART.Length; i++)
{
PAGERPORT.Write(PAGERSTART , i, 1);
}
PagerNo = PagerNo.PadLeft(4, '0').ToString();
byte[] PagerNoData= Encoding.Default.GetBytes(PagerNo);
if (!PAGERPORT.IsOpen)
PAGERPORT.Open();
for (int i = 0; i < PagerNoData.Length; i++)
{
PAGERPORT.Write(PagerNoData, i, 1);
}
if (!PAGERPORT.IsOpen)
PAGERPORT.Open();
for (int i = 0; i < PAGEREND .Length; i++)
{
PAGERPORT.Write(PAGEREND , i, 1);
}
}
catch
{
return;
}
}
Delphi或C#與信用卡連接的方式,有直接透過com port通訊或是透過呼叫exe的方式,利用in.txt、out.txt做溝通。然後回傳信用卡卡號/授權碼/刷卡金額等資訊。
示範一下Delphi與C#如何做信用卡線上刷卡。
Delphi
public
{ Public declarations }
ExecInfo : TShellExecuteInfo; // use shellapi
i:integer;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
s:String;
ts:TStringlist;
begin
ZeroMemory(@ExecInfo,SizeOf(ExecInfo));
with ExecInfo do begin
cbSize := SizeOf(ExecInfo);
fMask := SEE_MASK_NOCLOSEPROCESS;
lpVerb := 'open';
lpFile := 'ecr.exe';
Wnd := self.Handle;
nShow := SW_HIDE;
end;
s:='xxxxxxxxxxxxxxxxxxxx'; // 填上信用卡的溝通格式
ts := Tstringlist.Create;
ts.Clear;
ts.Add(s);
ts.SaveToFile('in.dat');
ts.Free;
ShellExecuteEx(@ExecInfo);
deletefile('out.dat');
caption := '刷卡中...';
timer1.Enabled := True;
i:=0;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var ts1:Tstringlist;
sstatus,smoney,scard,sappno:String;
begin
i:=i+1;
if fileexists('out.dat') then begin
Timer1.Enabled := false;
ts1 := Tstringlist.Create;
ts1.LoadFromFile('out.dat');
if ts1.Count >0 then begin
// 讀入檔案,解析格式
end;
ts1.Free;
end;
end;
string dir = System.Windows.Forms.Application.StartupPath;
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
private void uForm1_Load(object sender, EventArgs e)
{
try
{
if (File.Exists(dir + "/out.txt")) //刪除out.txt
File.Delete(dir + "/out.txt");
string code = ""; // in.txt格式
using (StreamWriter sw = new StreamWriter(dir + "/in.txt")) //小寫TXT
sw.Write(code);
IntPtr PDC = FindWindow(null, "ecr"); //開啟PosDataCom
if (PDC == (IntPtr)0)
{
try
{
Process p = new Process();
p.StartInfo.FileName = dir + "/ecrnccc.exe";
p.StartInfo.WorkingDirectory = dir;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
}
catch (Exception exp)
{
return;
}
}
this.timer1.Enabled = true;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (times == 5)
{
times = 0;
i++;
if (i > 4)
{
i = 0;
try
{
if (File.Exists(dir + "/out.txt"))
{
using (StreamReader sr = new StreamReader(dir + "/out.txt")) //小寫TXT
{
String line;
if ((line = sr.ReadLine()) != null)
{
// 解析
}
else
return false;
return true;
}
}
return false;
}
catch
{
return false;
}
}
}
times++;
}
WP-T810是目前支援列印QRCode的機型,適合拿來印電子發票。安裝步驟也不困難,先安裝Chip Driver後,就可以把USB模擬成Com Port,重開機後再安裝Windows Driver就可以拿來印電子發票了。
不過要注意一點是,安裝完後,記得在Paper Cut設定End of Each PAGE。
相關連結: Vectronix System Inc微創系統
好像常被問到POS機器上的發票要如何更換收執跟存根這件事!乾脆就拍了些照片分享出來

一、發票機上蓋打開後,會發現有二個槽,右邊的叫做發票存根聯(存根聯是店家自己留存用的,而且應依稅捐稽徵機關管理營利事業會計帳簿憑證辦法第27條規定,除應永久保存或有關未結會計事項者外,於會計年度決算程序辦理終了後,至少保存5年。);左邊的叫做發票收執聯(收執聯是店家給消費者保管,對獎用)。

二、我們先裝存根聯,把黑色定位點朝上

三、接下來按照方向從箭頭處穿入,壓住旁邊的壓桿穿出(沒壓住的話會被擋住)

四、接著把紙張插入存根捲紙軸中,記得是順時針方向

五、完成存根聯安裝

六、收執聯也一樣是黑色定位點朝上

七、依照箭頭穿入紙張,按住旁邊的壓桿讓紙張穿出
八、完成後,蓋回上蓋,按住存根進紙以及收執進紙不放讓二聯定位完成即可

九、就可以印出漂亮的發票了
相關法令: 營業人使用收銀機辦法
http://law.moj.gov.tw/LawClass/LawContent.aspx?PCODE=G0340084
[pascal]
procedure openport(PrinterName:pchar);stdcall;far; external ‘tsclib.dll’;
procedure closeport; external ‘tsclib.dll’;
procedure sendcommand(Command:pchar);stdcall;far;external ‘tsclib.dll’;
procedure setup(LabelWidth, LabelHeight, Speed, Density, Sensor, Vertical,
Offset:pchar);tsdcall; far; external ‘tsclib.dll’;
procedure downloadpcx(Filename,ImageName:pchar);stdcall;far;
external ‘tsclib.dll’;
procedure barcode(X, Y, CodeType, Height, Readable, Rotation, Narrow,
Wide, Code :pchar); stdcall; far; external ‘tsclib.dll’;
procedure printerfont(X, Y, FontName, Rotation, Xmul, Ymul, Content:pchar);
stdcall;far; external ‘tsclib.dll’;
procedure clearbuffer; external ‘tsclib.dll’;
procedure printlabel(NumberOfSet, NumberOfCopoy:pchar);stdcall; far;
external ‘tsclib.dll’;
procedure formfeed;external ‘tsclib.dll’;
procedure nobackfeed; external ‘tsclib.dll’
procedure windowsfont (X, Y, FontHeight, Rotation, FontStyle,
FontUnderline : integer; FaceName,
TextContect:pchar);stdcall;far;external ‘tsclib.dll’;
[/pascal]
1. openport(a)
說明: 指定電腦端的輸出埠
參數:
a: 字串型別
(1) 單機列印時,請指定印表機驅動程式名稱
例如: TSC CLEVER TTP-243
(2) 若連接印表機伺服器,請指定伺服器路徑及共用印表機名稱
例如: \\SERVER\TTP243
(3) 直接指定平行傳輸介面,請指定輸出埠名稱為 LPT1 到 LPT4
(4) 直接指定 USB 傳輸介面,請指定輸出埠名稱為 USB
2. closeport()
說明: 關閉指定的電腦端輸出埠
參數: 無
3. setup(a,b,c,d,e,f,g)
說明: 設定標籤的寬度、高度、列印速度、列印濃度、感應器類別、gap/black mark
垂直間距、gap/black mark 偏移距離)
參數:
a: 字串型別,設定標籤寬度,單位 mm
b: 字串型別,設定標籤高度,單位 mm
c: 字串型別,設定列印速度,(列印速度隨機型不同而有不同的選項)
1.0: 每秒 1.0 吋列印速度
1.5: 每秒 1.5 吋列印速度
2.0: 每秒 2.0 吋列印速度
3.0: 每秒 3.0 吋列印速度
4.0: 每秒 4.0 吋列印速度
6.0: 每秒 6.0 吋列印速度
8.0: 每秒 8.0 吋列印速度
10.0: 每秒 10.0 吋列印速度
d: 字串型別,設定列印濃度,
0~15,數字愈大列印結果愈黑
e: 字串型別,設定使用感應器類別
0 表示使用垂直間距感測器(gap sensor)
1 表示使用黑標感測器(black mark sensor)
f: 字串型別,設定 gap/black mark 垂直間距高度,單位: mm
g: 字串型別,設定 gap/black mark 偏移距離,單位: mm,此參數若使用一
般標籤時均設為 0
4. clearbuffer()
說明: 清除
參數: 無
5. barcode(a,b,c,d,e,f,g,h,I)
說明: 使用條碼機內建條碼列印
參數:
a: 字串型別,條碼 X 方向起始點,以點(point)表示。
(200 DPI,1 點=1/8 mm, 300 DPI,1 點=1/12 mm)
b: 字串型別,條碼 Y 方向起始點,以點(point)表示。
(200 DPI,1 點=1/8 mm, 300 DPI,1 點=1/12 mm)
c: 字串型別,
128 Code 128, switching code subset A, B, C
automatically
128M Code 128, switching code subset A, B, C
manually.
EAN128 Code 128, switching code subset A, B, C
automatically
25 Interleaved 2 of 5
25C Interleaved 2 of 5 with check digits
39 Code 39
39C Code 39 with check digits
93 Code 93
EAN13 EAN 13
EAN13+2 EAN 13 with 2 digits add-on
EAN13+5 EAN 13 with 5 digits add-on
EAN8 EAN 8
EAN8+2 EAN 8 with 2 digits add-on
EAN8+5 EAN 8 with 5 digits add-on
CODA Codabar
POST Postnet
UPCA UPC-A
UPCA+2 UPC-A with 2 digits add-on
UPCA+5 UPC-A with 5 digits add-on
UPCE UPC-E
UPCE+2 UPC-E with 2 digits add-on
UPCE+5 UPC-E with 5 digits add-on
d: 字串型別,設定條碼高度,高度以點來表示
e: 字串型別,設定是否列印條碼碼文
0: 不列印碼文
1: 列印碼文
f: 字串型別,設定條碼旋轉角度
0: 旋轉 0 度
90: 旋轉 90 度
180: 旋轉 180 度
270: 旋轉 270 度
g: 字串型別,設定條碼窄 bar 比例因子,請參考 TSPL 使用手冊
h: 字串型別,設定條碼窄 bar 比例因子,請參考 TSPL 使用手冊
I: 字串型別,條碼內容
6. printerfont(a,b,c,d,e,f,g)
說明: 使用條碼機內建文字列印
參數:
a: 字串型別,文字 X 方向起始點,以點(point)表示。
(200 DPI,1 點=1/8 mm, 300 DPI,1 點=1/12 mm)
b: 字串型別,文字 Y 方向起始點,以點(point)表示。
(200 DPI,1 點=1/8 mm, 300 DPI,1 點=1/12 mm)
c: 字串型別,內建字型名稱,共 12 種。
1: 8*/12 dots
2: 12*20 dots
3: 16*24 dots
4: 24*32 dots
5: 32*48 dots
TST24.BF2: 繁體中文 24*24
TST16.BF2: 繁體中文 16*16
TTT24.BF2: 繁體中文 24*24 (電信碼)
TSS24.BF2: 簡體中文 24*24
TSS16.BF2: 簡體中文 16*16
K: 韓文 24*24
L: 韓文 16*16
d: 字串型別,設定文字旋轉角度
0: 旋轉 0 度
90: 旋轉 90 度
180: 旋轉 180 度
270: 旋轉 270 度
e: 字串型別,設定文字 X 方向放大倍率,1~8
f: 字串型別,設定文字 X 方向放大倍率,1~8
g: 字串型別,列印文字內容
7. sendcommand(command)
說明: 送內建指令到條碼印表機
參數: 詳細指令請參考 TSPL
8. printlabel(a,b)
說明: 列印標籤內容
參數:
a: 字串型別,設定列印標籤式數(set)
b: 字串型別,設定列印標籤份數(copy)
9. downloadpcx(a,b)
說明:下載單色 PCX 格式圖檔至印表機
參數:
a: 字串型別,檔案名(可包含路徑)
b: 字串型別,下載至印表機記憶體內之檔名(請使用大寫檔名)
10. formfeed()
說明: 跳頁,該函式需在 setup 後使用
參數: 無
11. nobackfeed()
說明: 設定紙張不回吐
參數: 無
12. windowsfont(a,b,c,d,e,f,g,h)
說明: 使用 Windows TTF 字型列印文字
參數: a: 整數型別,文字 X 方向起始點,以點(point)表示
b: 整數型別,文字 Y 方向起始點,以點(point)表示。
c: 整數型別,字體高度,以點(point)表示。
d: 整數型別,旋轉角度,逆時鐘方向旋轉
0 -> 0 degree
90-> 90 degree
180-> 180 degree
270-> 270 degree
e: 整數型別,字體外形
0-> 標準(Normal)
1-> 斜體(Italic)
2-> 粗體(Bold)
3-> 粗斜體(Bold and Italic)
f: 整數型別, 底線
0-> 無底線
1-> 加底線
g: 字串型別,字體名稱。如: Arial, Times new Roman, 細名體, 標楷體
h: 字串型別,列印文字內容。
13. about()
說明: 顯示 DLL 版本號碼
參數: 無
Delphi有很好用的DBNavitor元件,美中不足的是按鈕的樣式稍嫌不足!那是否可以仿DBNavigator的方式?
筆者提供一個簡單的範例給大家 🙂

一、自訂首筆/上筆/下筆/末筆
[pascal]
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
BtnFirst.Enabled := not Datasource1.DataSet.Bof;
BtnPrior.Enabled := not Datasource1.DataSet.Bof;
BtnNext.Enabled := not Datasource1.DataSet.eof;
BtnLast.Enabled := not Datasource1.DataSet.eof;
if TDataSource(Sender).State in [dsEdit,dsInsert] then begin
BtnFirst.Enabled := False;
BtnPrior.Enabled := False;
BtnNext.Enabled := False;
BtnLast.Enabled := False;
end;
end;
[/pascal]
二、自訂新增/修改/刪除/取消/存檔
[pascal]
procedure TForm1.DataSource1StateChange(Sender: TObject);
begin
BtnAdd.Enabled := TDataSource(Sender).State in [dsbrowse];
BtnEdit.Enabled := TDataSource(Sender).State in [dsbrowse];
BtnDelete.Enabled := TDataSource(Sender).State in [dsBrowse];
BtnAbort.Enabled := TDataSource(Sender).State in [dsEdit,dsInsert];
BtnSave.Enabled := TDataSource(Sender).State in [dsEdit,dsInsert];
end;
[/pascal]
三、讓button按下後與DBNavigator一樣
[pascal]
procedure TForm1.BtnAbortClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbcancel);
end;
procedure TForm1.BtnAddClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbinsert);
end;
procedure TForm1.BtnDeleteClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbdelete);
end;
procedure TForm1.BtnEditClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbedit);
end;
procedure TForm1.BtnFirstClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbfirst);
end;
procedure TForm1.BtnLastClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nblast);
end;
procedure TForm1.BtnNextClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbnext);
end;
procedure TForm1.BtnPriorClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbprior);
end;
procedure TForm1.BtnSaveClick(Sender: TObject);
begin
dbnavigator1.BtnClick(nbpost);
end;
[/pascal]
前陣子做了一個「Delphi使用調查」,今天來發佈小小的結果。如果對是那家公司有興趣,就請加入 Delphi Developer【Delphi開發者】 社團。
