Compare commits

..

No commits in common. "main" and "v0.2" have entirely different histories.
main ... v0.2

7 changed files with 115 additions and 160 deletions

View File

@ -1,46 +1,3 @@
<p align="center">
<img src="./res/app.ico" width="200" />
</p>
<h1 align="center">TabEditor++</h1>
<p align="center">
一个制表符分隔的文本数据编辑工具
</p>
<p align="center" style="color:red;"><strong>使用 FlexCell 控件,请支持正版:<a href="https://www.grid2000.com/cn/index.html">https://www.grid2000.com/cn/index.html</a></strong></p>
# TabEditor--
TabEditor++仅适用于特定场景,小众应用。
## 📃 功能
- 读取以制表符分隔数据的txt文本编辑保存都不会更改其原本格式。
> 若用 Excel 打开这类txt文本保存时会将部分数据添加上双引号以及每行数据末尾都会出现多个多余的制表符
- 制表符分隔的txt文本数据与 sqlite3 数据格式转换
## ✨ 演示
![demo](./res/demo.png)
## 📝 更新日志
- [发行](https://gitea.iioio.com:3000/aardio/TabEditor/releases)
## ✨ 贡献
欢迎贡献、建议、错误报告和修复!
## 💖 致谢
感谢 aardio 的创造者 [aardio 官网](https://aardio.com/) aardio 历经 17 年活跃更新。小轻快,永久免费。一款超好用的 Windows 桌面软件开发工具!!!
感谢 光庆 大佬 [aardio 资源网](https://aar.chengxu.online/)
- flexcell —— 光庆大佬封装的 flexcell 库
- message —— 光庆大佬封装 [message 简单信息框](https://aar.chengxu.online/thread-18.htm)
感谢 FlexCell 作者 [FlexCell 官网](https://www.grid2000.com/cn/index.html),一款灵活易用的表格控件。
制表符分隔数据的txt文本编辑器

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<project ver="10" name="TabEditor++" libEmbed="true" icon="res\app.ico" ui="win" output="TabEditor++.exe" CompanyName="" FileDescription="TabEditor++" LegalCopyright="Copyright (C) iioio.com 2024" ProductName="TabEditor++" InternalName="TabEditor++" FileVersion="0.0.0.11" ProductVersion="0.0.0.11" publishDir="/dist/" dstrip="true" local="false" ignored="false">
<project ver="10" name="TabEditor++" libEmbed="true" icon="res\app.ico" ui="win" output="TabEditor++.exe" CompanyName="" FileDescription="TabEditor++" LegalCopyright="Copyright (C) iioio.com 2024" ProductName="TabEditor++" InternalName="TabEditor++" FileVersion="0.0.0.7" ProductVersion="0.0.0.7" publishDir="/dist/" dstrip="true" local="false" ignored="false">
<file name="main.aardio" path="main.aardio" comment="main.aardio"/>
<folder name="资源文件" path="res" embed="true" local="false" ignored="false">
<file name="app.ico" path="res\app.ico" comment="res\app.ico"/>

View File

@ -5,10 +5,9 @@ winform.add(
btnSearchNext={cls="button";text="查找下一个(F)";left=218;top=83;right=306;bottom=113;db=1;dl=1;font=LOGFONT(name='微软雅黑');z=1};
btnSearchPrev={cls="button";text="查找下上个(V)";left=119;top=83;right=207;bottom=113;db=1;dl=1;font=LOGFONT(name='微软雅黑');z=2};
button={cls="button";text="关闭";left=327;top=82;right=386;bottom=112;db=1;dl=1;font=LOGFONT(name='微软雅黑');z=4};
checkbox={cls="checkbox";text="区分大小写";left=19;top=60;right=111;bottom=87;bgcolor=16777215;font=LOGFONT(h=-14);z=6};
checkbox2={cls="checkbox";text="单元格匹配";left=19;top=92;right=111;bottom=119;bgcolor=16777215;font=LOGFONT(h=-14);z=7};
editSearchInput={cls="combobox";left=81;top=15;right=392;bottom=41;db=1;dl=1;edge=1;font=LOGFONT(name='微软雅黑');items={};mode="dropdown";z=3};
static={cls="static";text="查找内容:";left=12;top=16;right=72;bottom=42;align="right";bgcolor=16777215;center=1;db=1;dl=1;font=LOGFONT(name='微软雅黑');transparent=1;z=5}
checkbox={cls="checkbox";text="单元格匹配";left=16;top=86;right=108;bottom=113;bgcolor=16777215;checked=1;font=LOGFONT(h=-14);z=6};
editSearchInput={cls="combobox";left=81;top=28;right=392;bottom=54;db=1;dl=1;edge=1;font=LOGFONT(name='微软雅黑');items={};mode="dropdown";z=3};
static={cls="static";text="查找内容:";left=12;top=29;right=72;bottom=55;align="right";bgcolor=16777215;center=1;db=1;dl=1;font=LOGFONT(name='微软雅黑');transparent=1;z=5}
)
/*}}*/
@ -38,7 +37,7 @@ winform.onCancel = function(){
}
pushSearchNext = function(){
publish("search_next", winform.editSearchInput.text, winform.checkbox.checked, winform.checkbox2.checked);
publish("search_next", winform.editSearchInput.text, winform.checkbox.checked);
}
winform.onOk = function(){

View File

@ -130,7 +130,7 @@ class TeMenu{
[9] = {
tips = "txt 导出 Sqlite3";
text = '\uE612';
font = LOGFONT(h=this.ico_size+5;name='iconfont');
font = LOGFONT(h=this.ico_size;name='iconfont');
style = {
background={};
foreground={};
@ -144,7 +144,7 @@ class TeMenu{
[10] = {
tips = "Sqlite3 导出 txt";
text = '\uE612';
font = LOGFONT(h=this.ico_size+5;name='iconfont');
font = LOGFONT(h=this.ico_size;name='iconfont');
style = {
background={};
foreground={};
@ -264,53 +264,86 @@ class TeMenu{
};
this.init();
};
getSid = function(side, idx) {
var std = {};
if (side == 0) {
std.sd = "plus_left";
std.n = #this.toolbars_left;
} else {
std.sd = "plus_right";
std.n = #this.toolbars_right;
}
if (idx > 0 && idx <= std.n) {
std.ctrl = winform[std.sd ++ idx];
return std;
}
return;
}
setCommandFunc = function(side, idx, func){
var std = this.getSid(side, idx);
if (std) {
std.ctrl.oncommand = func(std.ctrl);
} else {
return;
select(side) {
case 0 {
if (idx > 0 and idx <= #this.toolbars_left) {
var ctrl = winform['plus_left'+idx];
winform['plus_left'+idx].oncommand = func(ctrl);
}
else {
return false;
}
}
case 1 {
if (idx > 0 and idx <= #this.toolbars_right) {
var ctrl = winform['plus_right'+idx];
winform['plus_right'+idx].oncommand = func(ctrl);
}
else {
return false;
}
}
else {
return false;
}
}
};
setRightClickFunc = function(side, idx, func){
var std = this.getSid(side, idx);
if (std) {
std.ctrl.wndproc = function(hwnd, message, wParam, lParam) {
select(side) {
case 0 {
if (idx > 0 and idx <= #this.toolbars_left) {
var ctrl = winform['plus_left'+idx];
winform['plus_left'+idx].wndproc = function(hwnd,message,wParam,lParam){
if (message == 0x205/*_WM_RBUTTONUP*/) {
func(std.ctrl);
func(ctrl);
}
}
} else {
return;
}
else {
return false;
}
}
case 1 {
if (idx > 0 and idx <= #this.toolbars_right) {
var ctrl = winform['plus_right'+idx];
winform['plus_right'+idx].wndproc = function(hwnd,message,wParam,lParam){
if (message == 0x205/*_WM_RBUTTONUP*/) {
func(ctrl);
}
}
}
else {
return false;
}
}
else {
return false;
}
}
}
disabled = function(side, idx, status){
var std = this.getSid(side, idx);
if (std) {
std.ctrl.disabled = status;
} else {
return;
select(side) {
case 0 {
if (idx > 0 and idx <= #this.toolbars_left) {
winform['plus_left'+idx].disabled = status;
}
else {
return false;
}
}
case 1 {
if (idx > 0 and idx <= #this.toolbars_right) {
winform['plus_right'+idx].disabled = status;
}
else {
return false;
}
}
else {
return false;
}
}
};
}

View File

@ -141,7 +141,6 @@ getTxtTableData = function(reference_row = 2){
var writeTxtFile = function(file_path, vlist_data){
var file = ..io.open(file_path,"w");
setCurFilePath(file_path);
for(i=1;#vlist_data;1){
var arrLine = {};
for(j=1;#vlist_data.fields;1){

View File

@ -25,7 +25,6 @@ mainForm.release = function(){
collectgarbage("collect");
}
var frmChild = mainForm.loadForm("\dlg\searchForm.aardio");
var g_mainform_text_default = mainForm.text;
//菜单控件初始化
g_teMenus = teMenu.TeMenu(mainForm.plus);
@ -81,8 +80,6 @@ g_teMenus.openFile = function(ctrl){
return function(){
var t = teUtils.getTxtTableData();
if(t){
mainForm.text = g_mainform_text_default;
mainForm.text += "[ " + teUtils.getCurFilePath() + " ]";
g_teMenus.newFile();
mainForm.g_flexcell.AutoRedraw = false;
mainForm.g_flexcell.setTable(t,,t.fields);
@ -94,7 +91,6 @@ g_teMenus.openFile = function(ctrl){
mainForm.g_flexcell.Refresh();
collectgarbage("collect");
collectgarbage("collect");
showModifyStyle();
}
}
}
@ -111,7 +107,6 @@ g_teMenus.saveFile = function(ctrl){
g_teMenus.saveAsFile = function(ctrl){
return function(){
teUtils.saveAsTxtTableData(mainForm.g_flexcell.getVlistData());
mainForm.text += "[ " + teUtils.getCurFilePath() + " ]";
showUnmodifyStyle();
}
}
@ -262,9 +257,7 @@ g_teMenus.exportTxt = function(ctrl){
//menu-关于
g_teMenus.showAbout = function(ctrl){
return function(){
import fsys.version;
var version = fsys.version.getInfo(io._exepath).productVersion;
mainForm.msgbox(version);
//mainForm.g_flexcell.AboutBox();
}
}
@ -343,11 +336,11 @@ mainForm.popmenuRight.add('向右插入一列',function(id){
mainForm.popmenuRight.add('删除列',function(id){
var curSelection = mainForm.g_flexcell.selection();
//TODO
mainForm.msgbox("暂无删除列功能--TODO");
curSelection.release();
mainForm.release();
} )
mainForm.g_flexcell.onMouseUp = function(Button , Shift, x, y){
/*** 鼠标按键放开。
Button 当前按下的鼠标按钮1左按钮2右按钮4中间按钮同时按下时执行位或操作。
@ -378,9 +371,23 @@ mainForm.g_flexcell.onSelChange = function(FirstRow,FirstCol,LastRow,LastCol){
}
/*}}*/
//搜索窗口
var openSearchForm = function(){
frmChild.show();
frmChild.editSearchInput.setFocus();
}
var accelerator = win.ui.accelerator({
{
ctrl = true; vkey = 'F'#;
oncommand = function() openSearchForm();
};
},mainForm );
research_flag = true;
searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCaseSensitive, isCellMatching){
searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCellMatching){
if(isRangeSearch){// 从一个范围开始搜索
//console.dump("从一个范围开始搜索");
var tempRow = firstRow;
var tempCol = firstCol;
firstRow = pre_searched_row != null and research_flag ? pre_searched_row : firstRow;
@ -390,22 +397,15 @@ searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRange
continue;
}
for i2,v2 in table.eachIndex(data.fields){
//console.debug("当前搜索行列:", i, i2);
if(i2 < firstCol or i2 > lastCol){
continue;
}
if (i == pre_searched_row and i2 == pre_searched_col){
continue;
}
var currStr = v[v2];
if(#currStr == 0 and #searchContent != 0){
continue;
}
if(!isCaseSensitive){
currStr = string.lower(currStr);
searchContent = string.lower(searchContent);
}
if (isCellMatching){
if(currStr == searchContent){
if(v[v2] == searchContent){
research_flag = true;
pre_searched_row = i;
pre_searched_col = i2;
@ -413,7 +413,7 @@ searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRange
}
}
else {
if(string.find(currStr, searchContent) or currStr == searchContent){
if(string.find(v[v2], searchContent)){
research_flag = true;
pre_searched_row = i;
pre_searched_col = i2;
@ -427,41 +427,33 @@ searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRange
// 搜不到了,重头搜索
if(research_flag){
research_flag = false;
pre_searched_row = null;
pre_searched_col = null;
row, col = searchNextContent(data, selFirstRow, selFirstCol, lastRow, lastCol, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCaseSensitive, isCellMatching);
row, col = searchNextContent(data, selFirstRow, selFirstCol, lastRow, lastCol, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCellMatching);
return row, col;
}
research_flag = true;
}
else {// 从一个点开始搜索
//console.dump("从一个点开始搜索");
for i,v in table.eachIndex(data){
if(i < firstRow){
continue;
}
for i2,v2 in table.eachIndex(data.fields){
//console.debug("当前搜索行列:", i, i2);
if(i2 < firstCol){
continue
}
if(i == firstRow and i2 == firstCol){
continue;
}
var currStr = v[v2];
if(#currStr == 0 and #searchContent != 0){
continue;
}
if(!isCaseSensitive){
currStr = string.lower(currStr);
searchContent = string.lower(searchContent);
}
if (isCellMatching){
if(currStr == searchContent){
if(v[v2] == searchContent){
research_flag = true;
return i, i2;
}
}
else {
if(string.find(currStr, searchContent) or currStr == searchContent){
if(string.find(v[v2], searchContent)){
research_flag = true;
return i, i2;
}
@ -472,7 +464,8 @@ searchNextContent = function(data, firstRow, firstCol, lastRow, lastCol, isRange
// 搜不到了,重头搜索
if(research_flag){
research_flag = false;
row, col = searchNextContent(data, 1, 1, 1, 1, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCaseSensitive, isCellMatching);
//console.dump("搜不到了,重头搜索");
row, col = searchNextContent(data, 1, 1, 1, 1, isRangeSearch, selFirstRow, selFirstCol, searchContent, isCellMatching);
return row, col;
}
research_flag = true;
@ -488,8 +481,7 @@ subscribe("search_prev",function(...){
subscribe("search_next",function(...){
var args = {...};
var searchContent = args[1];
var isCaseSensitive = args[2];
var isCellMatching = args[3];
var isCellMatching = args[2];
var curSelection = mainForm.g_flexcell.selection();
var firstRow = curSelection.FirstRow;
var firstCol = curSelection.FirstCol;
@ -502,7 +494,7 @@ subscribe("search_next",function(...){
if(pre_searched_row != null and pre_searched_col != null){
mainForm.g_flexcell.Cell(pre_searched_row, pre_searched_col).BackColor = 0xffffff;
}
var row, col = searchNextContent(mainForm.g_flexcell.getVlistData(), firstRow, firstCol, lastRow, lastCol, isRangeSearch, firstRow, firstCol, searchContent, isCaseSensitive, isCellMatching);
var row, col = searchNextContent(mainForm.g_flexcell.getVlistData(), firstRow, firstCol, lastRow, lastCol, isRangeSearch, firstRow, firstCol, searchContent, isCellMatching);
//console.dump(row, col);
if(row != null && col != null){
if(isRangeSearch){
@ -523,31 +515,6 @@ subscribe("search_next",function(...){
curSelection.release();
} )
//搜索窗口
var openSearchForm = function(){
frmChild.show();
frmChild.editSearchInput.setFocus();
}
var accelerator = win.ui.accelerator({
{
ctrl = true; vkey = 'F'#;
oncommand = function() openSearchForm();
};
{
ctrl = true; vkey = 'S'#;
oncommand = function(){
var curRow = mainForm.g_flexcell.ActiveCell().Row;
var curCol = mainForm.g_flexcell.ActiveCell().Col;
mainForm.g_flexcell.Cell(curRow, curCol).SetFocus(); // 不加这个,光标处于的单元格内容不会被保存----规避方案
teUtils.saveTxtTableData(mainForm.g_flexcell.getVlistData());
showUnmodifyStyle();
};
};
},mainForm );
import win.ui.minmax;
win.ui.minmax(mainForm,860,400);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB