/// <summary>
    /// 对比新旧两张Excel母表,返回旧表中含有但新表中已删除的Key所在旧表中的数据索引、新表中新增Key所在新表中的数据索引、新表中的主语言翻译相对旧表变动的Key所在新表中的数据索引(下标均从0开始)
    /// </summary>
    public static void CompareExcelFile(LangExcelInfo langExcelInfo, LangExcelInfo oldLangExcelInfo, out List <int> delectedKeyIndex, out List <int> newKeyIndex, out List <int> translationChangedIndex)
    {
        delectedKeyIndex        = new List <int>();
        newKeyIndex             = new List <int>();
        translationChangedIndex = new List <int>();

        List <LanguageInfo> languageInfoList    = langExcelInfo.GetAllLanguageInfoList();
        List <LanguageInfo> oldLanguageInfoList = oldLangExcelInfo.GetAllLanguageInfoList();

        // 查找新表中已删除的Key
        List <string> keys    = langExcelInfo.Keys;
        List <string> oldKeys = oldLangExcelInfo.Keys;

        int oldKeyCount = oldKeys.Count;

        for (int i = 0; i < oldKeyCount; ++i)
        {
            string oldKey = oldKeys[i];
            if (oldKey != null && !keys.Contains(oldKey))
            {
                delectedKeyIndex.Add(i);
            }
        }
        // 查找新增Key、主语言翻译变动
        int           keyCount = keys.Count;
        List <string> defaultLanguageDataList    = langExcelInfo.DefaultLanguageInfo.Data;
        List <string> oldDefaultLanguageDataList = oldLangExcelInfo.DefaultLanguageInfo.Data;

        for (int i = 0; i < keyCount; ++i)
        {
            string key = keys[i];
            if (key == null)
            {
                continue;
            }
            else if (!oldKeys.Contains(key))
            {
                newKeyIndex.Add(i);
            }
            else
            {
                string data = defaultLanguageDataList[i];
                if (data == null)
                {
                    continue;
                }
                else
                {
                    int    dataIndexInOldLanguageFile = oldLangExcelInfo.KeyToDataIndex[key];
                    string oldData = oldDefaultLanguageDataList[dataIndexInOldLanguageFile];
                    if (!data.Equals(oldData))
                    {
                        translationChangedIndex.Add(i);
                    }
                }
            }
        }
    }
Esempio n. 2
0
        // 点击“打开Excel母表”按钮
        private void btnOpenExcelFile_Click(object sender, EventArgs e)
        {
            string excelFilePath = txtExcelPath.Text.Trim();

            if (string.IsNullOrEmpty(excelFilePath))
            {
                MessageBox.Show("请先输入或选择国际化Excel母表所在路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            FileState fileState = Utils.GetFileState(excelFilePath);

            if (fileState == FileState.Inexist)
            {
                MessageBox.Show("输入的国际化Excel母表所在路径不存在,建议点击\"选择\"按钮进行文件选择", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!AppValues.EXCEL_FILE_EXTENSION.Equals(Path.GetExtension(excelFilePath), StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show(string.Format("本工具仅支持读取扩展名为{0}的Excel文件", AppValues.EXCEL_FILE_EXTENSION), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (fileState == FileState.IsOpen)
            {
                MessageBox.Show("该Excel文件正被其他软件打开,请关闭后重试", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 读取设置的注释行开头字符
            _SetCommentLineStartChar();

            // 解析Excel母表
            string        errorString   = null;
            LangExcelInfo langExcelInfo = AnalyzeHelper.AnalyzeLangExcelFile(excelFilePath, AppValues.CommentLineStartChar, out errorString);

            if (errorString == null)
            {
                AppValues.ExcelFullPath = Path.GetFullPath(excelFilePath);
                // 当重新选择了Excel母表文件后重置窗口控件
                _ChangeStateWhenSetExcelPath(false);
                AppValues.LangExcelInfo = langExcelInfo;
                // 设置了合法的Excel母表后,可以使用各个子模块功能
                _ChangeStateWhenSetExcelPath(true);
            }
            else
            {
                MessageBox.Show(string.Format("选定的Excel母表存在以下错误,请修正后重试\n\n{0}", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
    /// <summary>
    /// 复制最新母表,将翻译完的Excel文件内容与之合并,并将合并结果报告写入新建的Excel文件中
    /// </summary>
    public static bool ExportMergedExcelFile(string mergedExcelSavePath, string reportExcelSavePath, LangExcelInfo langExcelInfo, LangExcelInfo translatedLangExcelInfo, List <string> mergeLanguageNames, out string errorString)
    {
        int languageCount = mergeLanguageNames.Count;
        // 记录合并翻译时发现的新版母表与翻译完的Excel文件中Key相同但主语言翻译不同信息
        List <MergedResultDifferentDefaultLanguageInfo> differentDefaultLanguageInfo = new List <MergedResultDifferentDefaultLanguageInfo>();
        // 记录合并翻译时发现的新版母表与翻译完的Excel文件中Key不同信息
        List <MergedResultDifferentKeyInfo> differentKeyInfo = new List <MergedResultDifferentKeyInfo>();
        // 记录各个报告部分起始行行号
        List <int> partStartRowIndexList = new List <int>();

        partStartRowIndexList.Add(1);

        // 复制新版母表
        FileState fileState = Utils.GetFileState(AppValues.ExcelFullPath);

        if (fileState == FileState.Inexist)
        {
            errorString = string.Format("新版母表所在路径({0})已不存在,请勿在使用本工具过程中对母表文件进行操作,合并操作被迫中止", AppValues.ExcelFullPath);
            return(false);
        }
        try
        {
            File.Copy(AppValues.ExcelFullPath, mergedExcelSavePath, true);
        }
        catch (Exception exception)
        {
            errorString = string.Format("复制新版母表({0})至指定路径({1})失败:{2},合并操作被迫中止", AppValues.ExcelFullPath, mergedExcelSavePath, exception.Message);
            return(false);
        }

        // 打开复制后的母表,将翻译完的Excel文件中的内容与之合并
        Excel.Application mergedApplication = new Excel.Application();
        // 不显示Excel窗口
        mergedApplication.Visible = false;
        // 不显示警告对话框
        mergedApplication.DisplayAlerts = false;
        // 禁止屏幕刷新
        mergedApplication.ScreenUpdating = false;
        // 编辑非空单元格时不进行警告提示
        mergedApplication.AlertBeforeOverwriting = false;
        // 打开Excel工作簿
        Excel.Workbook mergedWorkbook = mergedApplication.Workbooks.Open(mergedExcelSavePath);
        // 找到名为data的Sheet表
        Excel.Worksheet mergedDataWorksheet = null;
        int             sheetCount          = mergedWorkbook.Sheets.Count;
        string          DATA_SHEET_NAME     = AppValues.EXCEL_DATA_SHEET_NAME.Replace("$", "");

        for (int i = 1; i <= sheetCount; ++i)
        {
            Excel.Worksheet sheet = mergedWorkbook.Sheets[i] as Excel.Worksheet;
            if (sheet.Name.Equals(DATA_SHEET_NAME))
            {
                mergedDataWorksheet = sheet;
                break;
            }
        }
        if (mergedDataWorksheet == null)
        {
            errorString = string.Format("新版母表({0})找不到Sheet名为{1}的数据表,请勿在使用本工具过程中对母表文件进行操作,导出操作被迫中止", AppValues.ExcelFullPath, DATA_SHEET_NAME);
            return(false);
        }

        // 还要新建一张新表,保存合并报告
        Excel.Application reportApplication = new Excel.Application();
        reportApplication.Visible                = false;
        reportApplication.DisplayAlerts          = false;
        reportApplication.ScreenUpdating         = false;
        reportApplication.AlertBeforeOverwriting = false;
        // 新建Excel工作簿
        Excel.Workbook reportWorkbook = reportApplication.Workbooks.Add();
        // 在名为合并报告的Sheet表中填充数据
        Excel.Worksheet reportWorksheet = reportWorkbook.Sheets[1] as Excel.Worksheet;
        reportWorksheet.Name = "合并报告";
        // 设置表格中所有单元格均为文本格式
        reportWorksheet.Cells.NumberFormatLocal = "@";
        // 报告Excel文件中依次按Key与主语言译文均相同、Key相同但主语言译文不同、母表不存在指定Key分成三部分进行报告
        // 不同部分之间隔开的行数
        const int SPACE_LINE_COUNT = 3;
        // Key与主语言译文相同的报告部分,列依次为Key名、母表行号、翻译完的Excel文件中的行号、主语言译文、各外语译文,其中用无色背景标识两表译文相同的单元格,用绿色背景标识母表未翻译而翻译完的Excel文件中新增译文的单元格,用黄色背景标识译文不同的单元格(并以批注形式写入母表中旧的译文)
        const int ALL_SAME_KEY_COLUMN_INDEX                      = 1;
        const int ALL_SAME_FILE_LINE_NUM_COLUMN_INDEX            = 2;
        const int ALL_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX = 3;
        const int ALL_SAME_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX   = 4;
        const int ALL_SAME_OTHER_LANGUAGE_START_COLUMN_INDEX     = 5;

        // 每个部分首行写入说明文字
        reportWorksheet.Cells[1, 1] = "以下为已合并的译文报告,其中用无色背景标识两表译文相同的单元格,用绿色背景标识母表未翻译而翻译完的Excel文件中新增译文的单元格,用黄色背景标识译文不同的单元格(并以批注形式写入母表中旧的译文)";
        // 写入Key与主语言译文均相同部分的列标题说明
        reportWorksheet.Cells[2, ALL_SAME_KEY_COLUMN_INDEX]                      = "Key名";
        reportWorksheet.Cells[2, ALL_SAME_FILE_LINE_NUM_COLUMN_INDEX]            = "母表中的行号";
        reportWorksheet.Cells[2, ALL_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX] = "翻译完的Excel表中的行号";
        reportWorksheet.Cells[2, ALL_SAME_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX]   = "主语言译文";
        for (int i = 0; i < languageCount; ++i)
        {
            int columnIndex = ALL_SAME_OTHER_LANGUAGE_START_COLUMN_INDEX + i;
            reportWorksheet.Cells[2, columnIndex] = mergeLanguageNames[i];
        }
        // 当前报告Excel表中下一个可用空行的行号(从1开始计)
        int nextCellLineNum = 3;
        // 逐行读取翻译完的Excel表中的内容并与最新母表比较,若Key相同主语言翻译相同,直接将翻译完的Excel表中对应的外语译文合并到母表,若Key相同但主语言翻译不同或者翻译完的Excel表中存在母表中已没有的Key则不合并且记入报告
        int translatedExcelDataCount = translatedLangExcelInfo.Keys.Count;

        for (int i = 0; i < translatedExcelDataCount; ++i)
        {
            string mergedExcelKey = translatedLangExcelInfo.Keys[i];
            if (mergedExcelKey == null)
            {
                continue;
            }

            // 判断母表中是否存在指定Key
            if (langExcelInfo.Keys.Contains(mergedExcelKey))
            {
                // 判断母表与翻译完的Excel文件中该Key对应的主语言译文是否相同
                // 母表中该Key所在行的数据索引
                int    excelDataIndex                      = langExcelInfo.KeyToDataIndex[mergedExcelKey];
                string excelDefaultLanguageValue           = langExcelInfo.DefaultLanguageInfo.Data[excelDataIndex];
                string translatedExcelDefaultLanguageValue = translatedLangExcelInfo.DefaultLanguageInfo.Data[i];
                if (excelDefaultLanguageValue.Equals(translatedExcelDefaultLanguageValue))
                {
                    // 如果该行外语的翻译均相同,则无需合并且不需要记入报告
                    bool isAllSame = true;
                    foreach (string languageName in mergeLanguageNames)
                    {
                        string excelLanguageValue      = langExcelInfo.OtherLanguageInfo[languageName].Data[excelDataIndex];
                        string translatedLanguageValue = translatedLangExcelInfo.OtherLanguageInfo[languageName].Data[i];
                        if (!excelLanguageValue.Equals(translatedLanguageValue))
                        {
                            isAllSame = false;
                            break;
                        }
                    }
                    // 存在不同的译文,则要合并到母表中并记入报告
                    if (isAllSame == false)
                    {
                        reportWorksheet.Cells[nextCellLineNum, ALL_SAME_KEY_COLUMN_INDEX]                      = mergedExcelKey;
                        reportWorksheet.Cells[nextCellLineNum, ALL_SAME_FILE_LINE_NUM_COLUMN_INDEX]            = excelDataIndex + AppValues.EXCEL_DATA_START_INDEX;
                        reportWorksheet.Cells[nextCellLineNum, ALL_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX] = i + AppValues.EXCEL_DATA_START_INDEX;
                        reportWorksheet.Cells[nextCellLineNum, ALL_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX] = i + AppValues.EXCEL_DATA_START_INDEX;
                        reportWorksheet.Cells[nextCellLineNum, ALL_SAME_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX]   = translatedExcelDefaultLanguageValue;

                        for (int j = 0; j < languageCount; ++j)
                        {
                            string languageName            = mergeLanguageNames[j];
                            string excelLanguageValue      = langExcelInfo.OtherLanguageInfo[languageName].Data[excelDataIndex];
                            string translatedLanguageValue = translatedLangExcelInfo.OtherLanguageInfo[languageName].Data[i];
                            int    columnIndex             = ALL_SAME_OTHER_LANGUAGE_START_COLUMN_INDEX + j;
                            // 报告中外语列单元格都要写入翻译完的Excel文件中对应的译文
                            reportWorksheet.Cells[nextCellLineNum, columnIndex] = translatedLanguageValue;
                            if (!excelLanguageValue.Equals(translatedLanguageValue))
                            {
                                int mergedExcelRowIndex    = excelDataIndex + AppValues.EXCEL_DATA_START_INDEX;
                                int mergedExcelColumnIndex = langExcelInfo.OtherLanguageInfo[languageName].ColumnIndex;

                                if (string.IsNullOrEmpty(excelLanguageValue))
                                {
                                    // 母表中原来没有译文,则将报告Excel表中对应单元格背景色设为绿色
                                    reportWorksheet.get_Range(reportWorksheet.Cells[nextCellLineNum, columnIndex], reportWorksheet.Cells[nextCellLineNum, columnIndex]).Interior.ColorIndex = 4;
                                }
                                else
                                {
                                    // 母表中和翻译完的Excel表中译文不同,则用黄色背景标识译文不同的单元格(并以批注形式写入母表中旧的译文)
                                    reportWorksheet.get_Range(reportWorksheet.Cells[nextCellLineNum, columnIndex], reportWorksheet.Cells[nextCellLineNum, columnIndex]).Interior.ColorIndex = 6;
                                    reportWorksheet.get_Range(reportWorksheet.Cells[nextCellLineNum, columnIndex], reportWorksheet.Cells[nextCellLineNum, columnIndex]).AddComment(string.Concat("母表中旧的译文:", System.Environment.NewLine, excelLanguageValue));
                                }

                                // 将翻译完的Excel表中的译文写入母表
                                mergedDataWorksheet.Cells[mergedExcelRowIndex, mergedExcelColumnIndex] = translatedLanguageValue;
                            }
                        }

                        ++nextCellLineNum;
                    }
                }
                else
                {
                    // Key相同,主语言译文不同则不合并且记入报告
                    MergedResultDifferentDefaultLanguageInfo info = new MergedResultDifferentDefaultLanguageInfo();

                    info.ExcelLineNum           = excelDataIndex + AppValues.EXCEL_DATA_START_INDEX;
                    info.TranslatedExcelLineNum = i + AppValues.EXCEL_DATA_START_INDEX;
                    info.Key = mergedExcelKey;
                    info.ExcelDefaultLanguageValue           = excelDefaultLanguageValue;
                    info.TranslatedExcelDefaultLanguageValue = translatedExcelDefaultLanguageValue;

                    differentDefaultLanguageInfo.Add(info);
                }
            }
            else
            {
                // 翻译完的Excel表中存在母表中已没有的Key则不合并且记入报告
                MergedResultDifferentKeyInfo info = new MergedResultDifferentKeyInfo();
                info.TranslatedExcelLineNum = i + AppValues.EXCEL_DATA_START_INDEX;
                info.Key = mergedExcelKey;
                info.TranslatedExcelDefaultLanguageValue = translatedLangExcelInfo.DefaultLanguageInfo.Data[i];

                differentKeyInfo.Add(info);
            }
        }
        // 设置框线及标题行格式
        _FormatPart(reportWorksheet, 1, nextCellLineNum - 1, ALL_SAME_OTHER_LANGUAGE_START_COLUMN_INDEX + languageCount - 1);

        // Key相同但主语言译文不同的报告部分,列依次为Key名、母表行号、翻译完的Excel文件中的行号、母表中主语言译文、翻译完的Excel文件中主语言译文
        const int KEY_SAME_KEY_COLUMN_INDEX                               = 1;
        const int KEY_SAME_FILE_LINE_NUM_COLUMN_INDEX                     = 2;
        const int KEY_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX          = 3;
        const int KEY_SAME_EXCEL_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX      = 4;
        const int KEY_SAME_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX = 5;

        if (differentDefaultLanguageInfo.Count > 0)
        {
            nextCellLineNum = nextCellLineNum + SPACE_LINE_COUNT;
            partStartRowIndexList.Add(nextCellLineNum);
            // 每个部分首行写入说明文字
            reportWorksheet.Cells[nextCellLineNum, 1] = "以下为母表与翻译完的Excel表中Key相同但主语言译文不同,无法进行合并的信息";
            ++nextCellLineNum;
            // 写入Key相同但主语言译文不同部分的列标题说明
            reportWorksheet.Cells[nextCellLineNum, KEY_SAME_KEY_COLUMN_INDEX]                               = "Key名";
            reportWorksheet.Cells[nextCellLineNum, KEY_SAME_FILE_LINE_NUM_COLUMN_INDEX]                     = "母表中的行号";
            reportWorksheet.Cells[nextCellLineNum, KEY_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX]          = "翻译完的Excel表中的行号";
            reportWorksheet.Cells[nextCellLineNum, KEY_SAME_EXCEL_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX]      = "母表中主语言译文";
            reportWorksheet.Cells[nextCellLineNum, KEY_SAME_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX] = "翻译完的Excel文件中主语言译文";
            ++nextCellLineNum;
            // 将所有Key相同但主语言译文不同信息写入报告
            foreach (MergedResultDifferentDefaultLanguageInfo info in differentDefaultLanguageInfo)
            {
                reportWorksheet.Cells[nextCellLineNum, KEY_SAME_KEY_COLUMN_INDEX]                               = info.Key;
                reportWorksheet.Cells[nextCellLineNum, KEY_SAME_FILE_LINE_NUM_COLUMN_INDEX]                     = info.ExcelLineNum;
                reportWorksheet.Cells[nextCellLineNum, KEY_SAME_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX]          = info.TranslatedExcelLineNum;
                reportWorksheet.Cells[nextCellLineNum, KEY_SAME_EXCEL_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX]      = info.ExcelDefaultLanguageValue;
                reportWorksheet.Cells[nextCellLineNum, KEY_SAME_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX] = info.TranslatedExcelDefaultLanguageValue;

                ++nextCellLineNum;
            }
        }
        // 设置框线及标题行格式
        _FormatPart(reportWorksheet, partStartRowIndexList[1], nextCellLineNum - 1, KEY_SAME_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX);

        // 母表不存在指定Key的报告部分,列依次为Key名、翻译完的Excel文件中的行号以及主语言译文
        const int KEY_DIFFERENT_KEY_COLUMN_INDEX = 1;
        const int KEY_DIFFERENT_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX          = 2;
        const int KEY_DIFFERENT_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX = 3;

        if (differentKeyInfo.Count > 0)
        {
            nextCellLineNum = nextCellLineNum + SPACE_LINE_COUNT;
            partStartRowIndexList.Add(nextCellLineNum);
            // 每个部分首行写入说明文字
            reportWorksheet.Cells[nextCellLineNum, 1] = "以下为翻译完的Excel文件含有但母表已经没有的Key,无法进行合并的信息";
            ++nextCellLineNum;
            // 写入母表中已没有的Key部分的列标题说明
            reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_KEY_COLUMN_INDEX] = "Key名";
            reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX]          = "翻译完的Excel表中的行号";
            reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX] = "翻译完的Excel文件中主语言译文";
            ++nextCellLineNum;
            // 将所有母表中已没有的Key信息写入报告
            foreach (MergedResultDifferentKeyInfo info in differentKeyInfo)
            {
                reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_KEY_COLUMN_INDEX] = info.Key;
                reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_TRANSLATED_FILE_LINE_NUM_COLUMN_INDEX]          = info.TranslatedExcelLineNum;
                reportWorksheet.Cells[nextCellLineNum, KEY_DIFFERENT_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX] = info.TranslatedExcelDefaultLanguageValue;

                ++nextCellLineNum;
            }
        }
        // 设置框线及标题行格式
        _FormatPart(reportWorksheet, partStartRowIndexList[2], nextCellLineNum - 1, KEY_DIFFERENT_TRANSLATED_DEFAULT_LANGUAGE_VALUE_COLUMN_INDEX);

        // 美化生成的Excel文件
        _BeautifyExcelWorksheet(reportWorksheet, 40, nextCellLineNum - 1);

        // 因为Excel中执行过合并的单元格即便设置了自动换行也无法实现效果,故为了防止每个部分首行的描述文字不完全可见,手工修改其行高
        for (int i = 0; i < partStartRowIndexList.Count; ++i)
        {
            int partStartRowIndex = partStartRowIndexList[i];
            reportWorksheet.get_Range("A" + partStartRowIndex).EntireRow.RowHeight = 80;
        }

        // 保存报告Excel文件
        reportWorksheet.SaveAs(reportExcelSavePath);
        reportWorkbook.SaveAs(reportExcelSavePath);
        // 关闭Excel
        reportWorkbook.Close(false);
        reportApplication.Workbooks.Close();
        reportApplication.Quit();
        Utils.KillExcelProcess(reportApplication);

        // 保存合并后的Excel文件
        mergedDataWorksheet.SaveAs(mergedExcelSavePath);
        mergedWorkbook.SaveAs(mergedExcelSavePath);
        // 关闭Excel
        mergedWorkbook.Close(false);
        mergedApplication.Workbooks.Close();
        mergedApplication.Quit();
        Utils.KillExcelProcess(mergedApplication);

        errorString = null;
        return(true);
    }
Esempio n. 4
0
    public static LangExcelInfo AnalyzeLangExcelFile(string filePath, string commentLineStartChar, out string errorString)
    {
        LangExcelInfo langExcelInfo = new LangExcelInfo();

        DataSet dataSet = XlsxReader.ReadXlsxFileByOleDb(filePath, out errorString);

        if (errorString != null)
        {
            return(null);
        }

        DataTable dataTable = dataSet.Tables[0];
        // 依次记录各语种的信息
        List <LanguageInfo> languageInfoList = new List <LanguageInfo>();
        // 依次记录各语种的名称,不允许同名语种
        List <string> languageNames = new List <string>();

        int rowCount    = dataTable.Rows.Count;
        int columnCount = dataTable.Columns.Count;

        if (rowCount < 2)
        {
            errorString = "Excel表格格式非法,必须在前两行声明语种描述和名称";
            return(null);
        }
        if (columnCount < 3)
        {
            errorString = "Excel表格格式非法,列自左向右应分别声明Key、主语言和至少一种外语";
            return(null);
        }

        // 从表格第2列开始,查找各语言所在列
        for (int i = 1; i < columnCount; ++i)
        {
            string languageName = dataTable.Rows[AppValues.EXCEL_NAME_ROW_INDEX - 1][i].ToString().Trim();
            if (!string.IsNullOrEmpty(languageName))
            {
                // 检查不同语种不允许名称相同
                if (languageNames.Contains(languageName))
                {
                    errorString = string.Format("表格第{0}行的语种名称定义中出现了名称均为\"{1}\"的两列,请修正后重试", AppValues.EXCEL_NAME_ROW_INDEX, languageName);
                    return(null);
                }
                else
                {
                    languageNames.Add(languageName);

                    LanguageInfo languageInfo = new LanguageInfo();
                    languageInfo.Desc        = dataTable.Rows[AppValues.EXCEL_DESC_ROW_INDEX - 1][i].ToString().Trim().Replace(System.Environment.NewLine, " ").Replace('\n', ' ').Replace('\r', ' ').Replace('\t', ' ');
                    languageInfo.Name        = languageName;
                    languageInfo.ColumnIndex = i + 1;

                    languageInfoList.Add(languageInfo);
                }
            }
        }
        if (languageInfoList.Count < 2)
        {
            errorString = "Excel母表格式非法,列自左向右应分别声明Key、主语言和至少一种外语";
            return(null);
        }

        // 记录所有的Key值,当Key为空或者以指定字符开头时认为是无效Key,存储为null
        List <string> keys = new List <string>();
        // 记录已读取的Key列值,不允许出现非空的重复Key(key:key值,value:从1开始计的行号)
        Dictionary <string, int> keyDict = new Dictionary <string, int>();
        // 记录重复Key所在行的信息(key:重复的Key名,value:此Key所在行列表,行号从1开始计)
        Dictionary <string, List <int> > repeatedKeyInfo = new Dictionary <string, List <int> >();
        // 记录主语言未进行翻译的行索引(从0开始计)
        List <int> notTranslatedRowIndex = new List <int>();

        // 逐行读取表格并生成所有语种的数据
        for (int dataIndex = AppValues.EXCEL_DATA_START_INDEX - 1; dataIndex < rowCount; ++dataIndex)
        {
            string keyString = dataTable.Rows[dataIndex][0].ToString().Trim();
            if (string.IsNullOrEmpty(keyString) || (commentLineStartChar != null && keyString.StartsWith(commentLineStartChar)))
            {
                keys.Add(null);
                for (int i = 0; i < languageInfoList.Count; ++i)
                {
                    LanguageInfo languageInfo = languageInfoList[i];
                    languageInfo.Data.Add(null);
                }
            }
            else
            {
                for (int i = 0; i < languageInfoList.Count; ++i)
                {
                    LanguageInfo languageInfo = languageInfoList[i];
                    string       inputData    = dataTable.Rows[dataIndex][languageInfo.ColumnIndex - 1].ToString();
                    languageInfo.Data.Add(inputData);
                }

                // 如果Key列值出现重复错误进行记录
                if (keyDict.ContainsKey(keyString))
                {
                    if (repeatedKeyInfo.ContainsKey(keyString))
                    {
                        List <int> repeatedKeyLineNums = repeatedKeyInfo[keyString];
                        repeatedKeyLineNums.Add(dataIndex + 1);
                    }
                    else
                    {
                        List <int> repeatedKeyLineNums = new List <int>();
                        repeatedKeyLineNums.Add(keyDict[keyString]);
                        repeatedKeyLineNums.Add(dataIndex + 1);
                        repeatedKeyInfo.Add(keyString, repeatedKeyLineNums);
                    }
                }
                else
                {
                    keys.Add(keyString);
                    keyDict.Add(keyString, dataIndex + 1);
                    langExcelInfo.KeyToDataIndex.Add(keyString, dataIndex - AppValues.EXCEL_NAME_ROW_INDEX);

                    // 检查主语言必须含有翻译
                    LanguageInfo defaultLanguageInfo = languageInfoList[0];
                    if (string.IsNullOrEmpty(defaultLanguageInfo.Data[dataIndex - AppValues.EXCEL_NAME_ROW_INDEX].ToString()))
                    {
                        notTranslatedRowIndex.Add(dataIndex);
                    }
                }
            }
        }
        StringBuilder errorStringBuilder = new StringBuilder();

        if (repeatedKeyInfo.Count > 0)
        {
            errorStringBuilder.AppendLine("以下行Key重复:");
            foreach (var item in repeatedKeyInfo)
            {
                string     key = item.Key;
                List <int> repeatedKeyLineNums = item.Value;
                errorStringBuilder.AppendFormat("名为\"{0}\"的Key在以下行中重复出现:{1}", key, Utils.CombineString <int>(repeatedKeyLineNums, ",")).AppendLine();
            }
        }
        if (notTranslatedRowIndex.Count > 0)
        {
            errorStringBuilder.AppendLine("以下行中主语言未填写对应文字:");
            for (int i = 0; i < notTranslatedRowIndex.Count; ++i)
            {
                int    rowIndex = notTranslatedRowIndex[i];
                string key      = keys[rowIndex - AppValues.EXCEL_NAME_ROW_INDEX];
                errorStringBuilder.AppendFormat("第{0}行(Key名为\"{1}\")", rowIndex + 1, key).AppendLine();
            }
        }

        errorString = errorStringBuilder.ToString();
        if (string.IsNullOrEmpty(errorString))
        {
            langExcelInfo.Keys = keys;
            langExcelInfo.DefaultLanguageInfo = languageInfoList[0];
            for (int i = 1; i < languageInfoList.Count; ++i)
            {
                LanguageInfo languageInfo = languageInfoList[i];
                langExcelInfo.OtherLanguageInfo.Add(languageInfo.Name, languageInfo);
            }

            errorString = null;
            return(langExcelInfo);
        }
        else
        {
            return(null);
        }
    }
Esempio n. 5
0
        // 点击“合并翻译完的Excel文件”按钮
        private void btnMergeTranslatedExcelFile_Click(object sender, EventArgs e)
        {
            // 检查是否指定了合法的合并后的Excel文件的保存路径
            string mergedExcelSavePath = txtMergedExcelPath.Text.Trim();

            if (string.IsNullOrEmpty(mergedExcelSavePath))
            {
                MessageBox.Show("必须输入合并后的Excel文件的保存路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!AppValues.EXCEL_FILE_EXTENSION.Equals(Path.GetExtension(mergedExcelSavePath), StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show(string.Format("合并后的Excel文件扩展名必须为{0}", AppValues.EXCEL_FILE_EXTENSION), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查要导出的后的Excel文件是否已存在且正被其他程序使用
            if (Utils.GetFileState(mergedExcelSavePath) == FileState.IsOpen)
            {
                MessageBox.Show("要覆盖的合并后的Excel文件正被其他程序打开,请关闭后重试", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查是否指定了合法的翻译完的Excel文件
            string translatedExcelPath = txtTranslatedExcelPath.Text.Trim();

            if (string.IsNullOrEmpty(translatedExcelPath))
            {
                MessageBox.Show("必须输入翻译完的Excel文件所在路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            FileState fileState = Utils.GetFileState(translatedExcelPath);

            if (fileState == FileState.Inexist)
            {
                MessageBox.Show("输入的翻译完的Excel文件所在路径不存在,建议点击\"选择\"按钮进行文件选择", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!AppValues.EXCEL_FILE_EXTENSION.Equals(Path.GetExtension(translatedExcelPath), StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show(string.Format("本工具仅支持读取扩展名为{0}的Excel文件", AppValues.EXCEL_FILE_EXTENSION), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (fileState == FileState.IsOpen)
            {
                MessageBox.Show("指定的翻译完的Excel文件正被其他软件打开,请关闭后重试", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查选择的翻译完的Excel文件和新版母表不能为同一个文件
            string translatedExcelFileFullPath = Path.GetFullPath(translatedExcelPath);

            if (translatedExcelFileFullPath.Equals(AppValues.ExcelFullPath))
            {
                MessageBox.Show("你选择的翻译完的Excel文件和新版母表是同一个文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 解析翻译完的Excel文件
            string        errorString         = null;
            LangExcelInfo translatedExcelInfo = AnalyzeHelper.AnalyzeLangExcelFile(translatedExcelPath, AppValues.CommentLineStartChar, out errorString);

            if (errorString != null)
            {
                MessageBox.Show(string.Format("选定的翻译完后的Excel文件存在以下错误,请修正后重试\n\n{0}", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查翻译完的Excel文件与新版母表的主语言名称是否相同
            string excelDefaultLanguageName           = AppValues.LangExcelInfo.DefaultLanguageInfo.Name;
            string translatedExcelDefaultLanguageName = translatedExcelInfo.DefaultLanguageInfo.Name;

            if (!excelDefaultLanguageName.Equals(translatedExcelDefaultLanguageName))
            {
                MessageBox.Show(string.Format("翻译完的Excel文件与新版母表的主语言名称不同,无法进行对比,请统一后重试\n新版母表中主语言名称:{0},翻译完的Excel文件中主语言名称:{1}", excelDefaultLanguageName, translatedExcelDefaultLanguageName), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 记录翻译完的Excel文件中存在的外语名
            List <string> translatedExcelFileOtherLanguageNames = new List <string>();
            // 检查翻译完的Excel文件中的外语在新版母表中是否都存在
            List <string> inexistentOtherLanguageName = new List <string>();

            foreach (string otherLanguageName in translatedExcelInfo.OtherLanguageInfo.Keys)
            {
                if (!AppValues.LangExcelInfo.OtherLanguageInfo.ContainsKey(otherLanguageName))
                {
                    inexistentOtherLanguageName.Add(otherLanguageName);
                }

                translatedExcelFileOtherLanguageNames.Add(otherLanguageName);
            }
            if (inexistentOtherLanguageName.Count > 0)
            {
                MessageBox.Show(string.Format("翻译完后的Excel文件中存在以下新版母表中不存在的外语名,无法进行合并\n{0}", Utils.CombineString <string>(inexistentOtherLanguageName, ",")), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查完毕执行合并功能并生成合并结果报告文件(保存路径与合并后的Excel文件相同)
            string reportExcelSavePath = Utils.CombinePath(Path.GetDirectoryName(mergedExcelSavePath), string.Format("合并报告 {0:yyyy年MM月dd日 HH时mm分ss秒}.xlsx", DateTime.Now));

            ExportExcelFileHelper.ExportMergedExcelFile(mergedExcelSavePath, reportExcelSavePath, AppValues.LangExcelInfo, translatedExcelInfo, translatedExcelFileOtherLanguageNames, out errorString);
            if (errorString == null)
            {
                DialogResult dialogResult = MessageBox.Show(string.Format("合并操作成功\n合并后的Excel文件存储路径为{0}\n报告文件存储路径为{1}\n\n点击“确定”按钮后将自动打开此报告文件", mergedExcelSavePath, reportExcelSavePath), "恭喜", MessageBoxButtons.OK, MessageBoxIcon.Information);
                if (dialogResult == DialogResult.OK)
                {
                    System.Diagnostics.Process.Start(reportExcelSavePath);
                }
            }
            else
            {
                errorString = string.Concat("合并操作失败:", errorString);
                MessageBox.Show(errorString, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Esempio n. 6
0
        // 点击“打开旧版母表”按钮
        private void btnOpenOldExcelFile_Click(object sender, EventArgs e)
        {
            string excelFilePath = txtOldExcelPath.Text.Trim();

            if (string.IsNullOrEmpty(excelFilePath))
            {
                MessageBox.Show("请先输入或选择与新版母表对比的旧版国际化Excel母表所在路径", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            FileState fileState = Utils.GetFileState(excelFilePath);

            if (fileState == FileState.Inexist)
            {
                MessageBox.Show("输入的旧版国际化Excel母表所在路径不存在,建议点击\"选择\"按钮进行文件选择", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (!AppValues.EXCEL_FILE_EXTENSION.Equals(Path.GetExtension(excelFilePath), StringComparison.CurrentCultureIgnoreCase))
            {
                MessageBox.Show(string.Format("本工具仅支持读取扩展名为{0}的Excel文件", AppValues.EXCEL_FILE_EXTENSION), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (fileState == FileState.IsOpen)
            {
                MessageBox.Show("该Excel文件正被其他软件打开,请关闭后重试", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // 检查选择的旧表和新表不能为同一个文件
            string oldExcelFileFullPath = Path.GetFullPath(excelFilePath);

            if (oldExcelFileFullPath.Equals(AppValues.ExcelFullPath))
            {
                MessageBox.Show("你选择的旧表和新表是同一个文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // 解析旧版Excel母表
            string        errorString   = null;
            LangExcelInfo langExcelInfo = AnalyzeHelper.AnalyzeLangExcelFile(excelFilePath, AppValues.CommentLineStartChar, out errorString);

            if (errorString == null)
            {
                // 检查新旧母表的主语言名称是否相同
                string excelDefaultLanguageName    = AppValues.LangExcelInfo.DefaultLanguageInfo.Name;
                string oldExcelDefaultLanguageName = langExcelInfo.DefaultLanguageInfo.Name;
                if (!excelDefaultLanguageName.Equals(oldExcelDefaultLanguageName))
                {
                    MessageBox.Show(string.Format("新旧母表主语言名称不同,无法进行对比,请统一后重试\n新版母表中主语言名称:{0},旧版中主语言名称:{1}", excelDefaultLanguageName, oldExcelDefaultLanguageName), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                // 检查新旧母表的所有外语名称是否相同
                bool isMatchOtherLanguageInfo = true;
                if (AppValues.LangExcelInfo.OtherLanguageInfo.Count == langExcelInfo.OtherLanguageInfo.Count)
                {
                    foreach (var item in AppValues.LangExcelInfo.OtherLanguageInfo)
                    {
                        if (!langExcelInfo.OtherLanguageInfo.ContainsKey(item.Key))
                        {
                            isMatchOtherLanguageInfo = false;
                            break;
                        }
                    }
                }
                else
                {
                    isMatchOtherLanguageInfo = false;
                }

                if (isMatchOtherLanguageInfo == false)
                {
                    MessageBox.Show("新旧母表的所有外语种类个数或者名称不完全匹配,无法进行对比", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                AppValues.OldLangExcelInfo = langExcelInfo;
                // 设置了合法的旧版Excel母表后,可以使用对比功能下属的各个子模块功能
                _ChangeStateWhenSetOldExcelPath(true);
            }
            else
            {
                MessageBox.Show(string.Format("选定的旧版Excel母表存在以下错误,请修正后重试\n\n{0}", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
    public static bool ExportLangFile(LangExcelInfo langExcelInfo, string languageName, string savePath, string keyAndValueSplitChar, out string errorString)
    {
        // 检查输入的路径是否合法
        string fullPath = null;

        try
        {
            fullPath = Path.GetFullPath(savePath);
        }
        catch
        {
            errorString = "路径非法";
            return(false);
        }
        string dirPath = Path.GetDirectoryName(fullPath);

        if (string.IsNullOrEmpty(Path.GetFileName(fullPath)))
        {
            errorString = "路径非法,未输入文件名";
            return(false);
        }
        if (!Directory.Exists(dirPath))
        {
            try
            {
                Directory.CreateDirectory(dirPath);
            }
            catch (Exception exception)
            {
                errorString = string.Format("创建目录({0})失败:{1}", dirPath, exception.Message);
                return(false);
            }
        }
        if (string.IsNullOrEmpty(Path.GetExtension(fullPath)))
        {
            fullPath = string.Concat(fullPath, ".", AppValues.LangFileExtension);
        }

        // 记录未填写译文的数据索引(下标从0开始)
        List <int> untranslatedDataIndex = new List <int>();
        // 记录要写入lang文件的内容
        StringBuilder langFileContent = new StringBuilder();

        List <string> keys           = langExcelInfo.Keys;
        List <string> translatedText = langExcelInfo.GetLanguageInfoByLanguageName(languageName).Data;
        int           keyCount       = keys.Count;

        for (int i = 0; i < keyCount; ++i)
        {
            if (keys[i] == null)
            {
                continue;
            }

            if (string.IsNullOrEmpty(translatedText[i]))
            {
                untranslatedDataIndex.Add(i);
                // 当发现有未翻译的问题时,该lang文件不会进行导出,后面也无需组织要写入lang文件的内容,只需继续检查后面是否还有未翻译的问题
                for (int j = i + 1; j < keyCount; ++j)
                {
                    if (keys[j] == null)
                    {
                        continue;
                    }

                    if (string.IsNullOrEmpty(translatedText[j]))
                    {
                        untranslatedDataIndex.Add(j);
                    }
                }
                break;
            }
            else
            {
                langFileContent.AppendLine(string.Concat(keys[i], keyAndValueSplitChar, translatedText[i]));
            }
        }

        if (untranslatedDataIndex.Count > 0)
        {
            StringBuilder errorStringBuilder = new StringBuilder();
            errorStringBuilder.AppendLine("错误:在以下行中存在未翻译的内容,请完全翻译后重试");
            foreach (int dataIndex in untranslatedDataIndex)
            {
                errorStringBuilder.AppendFormat("第{0}行,Key为\"{1}\"", dataIndex + AppValues.EXCEL_DATA_START_INDEX, keys[dataIndex]).AppendLine();
            }

            errorString = errorStringBuilder.ToString();
            return(false);
        }
        // 检查无误后生成lang文件
        if (Utils.SaveFile(fullPath, langFileContent.ToString(), out errorString) == true)
        {
            return(true);
        }
        else
        {
            errorString = string.Concat("生成lang文件失败:", errorString);
            return(false);
        }
    }