有許多單機版的進銷存系統、餐飲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開發者】 社團。