<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>智朋的个人博客</title>
  <icon>https://coffeelize.top/images/cat-avatar.jpg</icon>
  <subtitle>道阻且长，行则将至</subtitle>
  <link href="https://coffeelize.top/atom.xml" rel="self"/>
  
  <link href="https://coffeelize.top/"/>
  <updated>2025-03-28T01:55:40.677Z</updated>
  <id>https://coffeelize.top/</id>
  
  <author>
    <name>coffeelize</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Anki 笔记读取器</title>
    <link href="https://coffeelize.top/posts/Anki-Note-Reader.html"/>
    <id>https://coffeelize.top/posts/Anki-Note-Reader.html</id>
    <published>2024-10-05T07:25:26.000Z</published>
    <updated>2025-03-28T01:55:40.677Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="Anki-笔记数据库"><a href="#Anki-笔记数据库" class="headerlink" title="Anki 笔记数据库"></a>Anki 笔记数据库</h2><p>Anki 的笔记数据都存储在&nbsp;<code>collection.anki2</code>&nbsp;文件中，包含了用户的所有笔记、卡片、标签等信息</p><figure class="highlight python"><figcaption><span>文件路径 </span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\Administrator\AppData\Roaming\Anki2\账户<span class="number">1</span>\collection.anki2</span><br></pre></td></tr></tbody></table></figure><p>可以使用 SQLite 或 Python 的&nbsp;<code>sqlite3</code>&nbsp;模块连接并查询该数据库，查看具体的表和字段。</p><h2 id="本地笔记检索"><a href="#本地笔记检索" class="headerlink" title="本地笔记检索"></a>本地笔记检索</h2><h3 id="使用-sqlite3-链接数据库"><a href="#使用-sqlite3-链接数据库" class="headerlink" title="使用 sqlite3 链接数据库"></a>使用 sqlite3 链接数据库</h3><figure class="highlight python"><figcaption><span>打印 collection.anki2 数据库中的所有表格 </span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sqlite3  </span><br><span class="line">  </span><br><span class="line"><span class="comment"># 连接到 Anki 数据库（此处注意替换为自己的文件路径）  </span></span><br><span class="line">anki_db_path = <span class="string">r'C:\Users\Administrator\AppData\Roaming\Anki2\本地账户\collection.anki2'</span>  </span><br><span class="line">conn = sqlite3.connect(anki_db_path)  </span><br><span class="line">  </span><br><span class="line"><span class="comment"># 查看 notes 表的结构  </span></span><br><span class="line">cursor = conn.cursor()  </span><br><span class="line">cursor.execute(<span class="string">"PRAGMA table_info(notes);"</span>)  </span><br><span class="line">columns = cursor.fetchall()  </span><br><span class="line">  </span><br><span class="line"><span class="comment"># 打印字段名  </span></span><br><span class="line"><span class="keyword">for</span> column <span class="keyword">in</span> columns:  </span><br><span class="line">    <span class="built_in">print</span>(column)  </span><br><span class="line">  </span><br><span class="line"><span class="comment"># 关闭连接  </span></span><br><span class="line">conn.close()</span><br></pre></td></tr></tbody></table></figure><p>输出结果为</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">(<span class="number">0</span>, <span class="string">'id'</span>, <span class="string">'INTEGER'</span>, <span class="number">0</span>, <span class="literal">None</span>, <span class="number">1</span>)  </span><br><span class="line">(<span class="number">1</span>, <span class="string">'guid'</span>, <span class="string">'TEXT'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">2</span>, <span class="string">'mid'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">3</span>, <span class="string">'mod'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">4</span>, <span class="string">'usn'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">5</span>, <span class="string">'tags'</span>, <span class="string">'TEXT'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">6</span>, <span class="string">'flds'</span>, <span class="string">'TEXT'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">7</span>, <span class="string">'sfld'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">8</span>, <span class="string">'csum'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">9</span>, <span class="string">'flags'</span>, <span class="string">'INTEGER'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)  </span><br><span class="line">(<span class="number">10</span>, <span class="string">'data'</span>, <span class="string">'TEXT'</span>, <span class="number">1</span>, <span class="literal">None</span>, <span class="number">0</span>)</span><br></pre></td></tr></tbody></table></figure><p>说明可以正常连接数据库，准备工作已做好</p><h3 id="制作一个-Python-小程序读取数据库"><a href="#制作一个-Python-小程序读取数据库" class="headerlink" title="制作一个 Python 小程序读取数据库"></a>制作一个 Python 小程序读取数据库</h3><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> sqlite3</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> (</span><br><span class="line">    QApplication, QWidget, QVBoxLayout, QPushButton,</span><br><span class="line">    QLineEdit, QTextEdit, QMessageBox</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AnkiNoteReader</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line">        self.initUI()</span><br><span class="line">        self.notes_df = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initUI</span>(<span class="params">self</span>):</span></span><br><span class="line">        self.setWindowTitle(<span class="string">'Anki 笔记读取器'</span>)</span><br><span class="line"></span><br><span class="line">        layout = QVBoxLayout()</span><br><span class="line"></span><br><span class="line">        self.load_button = QPushButton(<span class="string">'加载笔记'</span>, self)</span><br><span class="line">        self.load_button.clicked.connect(self.load_notes)</span><br><span class="line">        layout.addWidget(self.load_button)</span><br><span class="line"></span><br><span class="line">        self.search_box = QLineEdit(self)</span><br><span class="line">        self.search_box.setPlaceholderText(<span class="string">'搜索关键词'</span>)</span><br><span class="line">        layout.addWidget(self.search_box)</span><br><span class="line"></span><br><span class="line">        self.search_button = QPushButton(<span class="string">'搜索'</span>, self)</span><br><span class="line">        self.search_button.clicked.connect(self.search_notes)</span><br><span class="line">        layout.addWidget(self.search_button)</span><br><span class="line"></span><br><span class="line">        self.text_area = QTextEdit(self)</span><br><span class="line">        layout.addWidget(self.text_area)</span><br><span class="line"></span><br><span class="line">        self.setLayout(layout)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">load_notes</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="comment"># 连接到 Anki 数据库</span></span><br><span class="line">            anki_db_path = <span class="string">r'C:\Users\Administrator\AppData\Roaming\Anki2\本地账户\collection.anki2'</span></span><br><span class="line">            conn = sqlite3.connect(anki_db_path)</span><br><span class="line">            query = <span class="string">'SELECT id, flds FROM notes'</span></span><br><span class="line">            self.notes_df = pd.read_sql_query(query, conn)</span><br><span class="line">            conn.close()</span><br><span class="line"></span><br><span class="line">            self.display_notes(self.notes_df)</span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">            QMessageBox.critical(self, <span class="string">"错误"</span>, <span class="built_in">str</span>(e))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">display_notes</span>(<span class="params">self, notes</span>):</span></span><br><span class="line">        self.text_area.clear()</span><br><span class="line">        <span class="keyword">for</span> index, row <span class="keyword">in</span> notes.iterrows():</span><br><span class="line">            <span class="comment"># 清除不可见字符，保留中文和其他可见字符</span></span><br><span class="line">            fields = re.sub(<span class="string">r'[^\u4e00-\u9fa5\x20-\x7E]'</span>, <span class="string">' '</span>, row[<span class="string">'flds'</span>])  <span class="comment"># 保留中文和可见字符</span></span><br><span class="line">            self.text_area.append(<span class="string">f"Note ID: <span class="subst">{row[<span class="string">'id'</span>]}</span>\nFields: <span class="subst">{fields.strip()}</span>\n"</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">search_notes</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="keyword">if</span> self.notes_df <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span>:</span><br><span class="line">            search_term = self.search_box.text()</span><br><span class="line">            <span class="keyword">if</span> search_term:</span><br><span class="line">                filtered_notes = self.notes_df[self.notes_df[<span class="string">'flds'</span>].<span class="built_in">str</span>.contains(search_term, na=<span class="literal">False</span>)]</span><br><span class="line">                self.display_notes(filtered_notes)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                self.display_notes(self.notes_df)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            QMessageBox.warning(self, <span class="string">"警告"</span>, <span class="string">"请先加载笔记！"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    ex = AnkiNoteReader()</span><br><span class="line">    ex.resize(<span class="number">600</span>, <span class="number">400</span>)</span><br><span class="line">    ex.show()</span><br><span class="line">    sys.exit(app.<span class="built_in">exec</span>())</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20241005153729.png" alt="image.png"></p><p>加载笔记以及搜索笔记如下图<br><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20241005153806.png" alt="image.png"></p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20241005153811.png" alt="image.png"></p><h2 id="远程笔记检索"><a href="#远程笔记检索" class="headerlink" title="远程笔记检索"></a>远程笔记检索</h2><h3 id="功能实现"><a href="#功能实现" class="headerlink" title="功能实现"></a>功能实现</h3><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request, jsonify  </span><br><span class="line"><span class="keyword">import</span> sqlite3  </span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd  </span><br><span class="line">  </span><br><span class="line">app = Flask(__name__)  </span><br><span class="line">  </span><br><span class="line"><span class="comment"># 数据库文件路径  </span></span><br><span class="line">DATABASE_PATH = <span class="string">r'C:\Users\Administrator\AppData\Roaming\Anki2\本地账户\collection.anki2'</span>  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">query_database</span>(<span class="params">query</span>):</span>  </span><br><span class="line">    <span class="string">"""执行 SQL 查询并返回结果为 DataFrame"""</span>    conn = sqlite3.connect(DATABASE_PATH)  </span><br><span class="line">    df = pd.read_sql_query(query, conn)  </span><br><span class="line">    conn.close()  </span><br><span class="line">    <span class="keyword">return</span> df  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/search'</span>, methods=[<span class="string">'GET'</span>]</span>)  </span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">search_notes</span>():</span>  </span><br><span class="line">    <span class="string">"""根据查询词搜索笔记"""</span>  </span><br><span class="line">    search_term = request.args.get(<span class="string">'term'</span>, <span class="string">''</span>)  </span><br><span class="line">    query = <span class="string">f"SELECT id, flds FROM notes WHERE flds LIKE '%<span class="subst">{search_term}</span>%'"</span>  </span><br><span class="line">  </span><br><span class="line">    <span class="keyword">try</span>:  </span><br><span class="line">        results = query_database(query)  </span><br><span class="line">        notes = results.to_dict(orient=<span class="string">'records'</span>)  </span><br><span class="line">        <span class="keyword">return</span> jsonify(notes)  </span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:  </span><br><span class="line">        <span class="keyword">return</span> jsonify({<span class="string">'error'</span>: <span class="built_in">str</span>(e)})  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:  </span><br><span class="line">    app.run(host=<span class="string">'0.0.0.0'</span>, port=<span class="number">5000</span>)  <span class="comment"># 可访问所有 IP</span></span><br></pre></td></tr></tbody></table></figure><p>运行后提示：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> * Serving Flask app <span class="string">'app'</span></span><br><span class="line"> * Debug mode: off</span><br><span class="line">WARNING: This <span class="keyword">is</span> a development server. Do <span class="keyword">not</span> use it <span class="keyword">in</span> a production deployment. Use a production WSGI server instead.</span><br><span class="line"> * Running on <span class="built_in">all</span> addresses (<span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span>)</span><br><span class="line"> * Running on http://<span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">5000</span></span><br><span class="line"> * Running on http://<span class="number">192.168</span><span class="number">.1</span><span class="number">.94</span>:<span class="number">5000</span></span><br></pre></td></tr></tbody></table></figure><p>这时，我们可以在浏览器输入</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://<span class="number">192.168</span><span class="number">.1</span><span class="number">.94</span>:<span class="number">5000</span>/search?term= 要搜索的内容</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20241005154109.png" alt="image.png"></p><h3 id="完善输出"><a href="#完善输出" class="headerlink" title="完善输出"></a>完善输出</h3><ul><li>增加搜索按钮</li><li>优化输出前端效果</li><li>表格形式输出</li><li>添加图片显示（需添加图片数据库地址）</li><li>添加导出 CSV 功能</li></ul><p>项目结构为：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">/project</span><br><span class="line">    /static</span><br><span class="line">        styles.css</span><br><span class="line">        javascript.js</span><br><span class="line">    /templates</span><br><span class="line">        index.html</span><br><span class="line">    app.py</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20241005161807.png" alt="image.png"></p><p><img data-src="https://s2.loli.net/2024/10/05/tYkZlIS1r2TyfoX.gif" alt="Anki.gif"></p><h4 id="主程序"><a href="#主程序" class="headerlink" title="主程序"></a>主程序</h4><p>以下代码中，需要将 Anki 数据库路径及图片媒体路径替换为自己电脑对应的路径</p><figure class="highlight python"><figcaption><span>app.py</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request, send_from_directory, render_template, send_file</span><br><span class="line"><span class="keyword">import</span> sqlite3</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> csv</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 数据库文件路径（需要替换成自己Anki数据库及图片路径）</span></span><br><span class="line">DATABASE_PATH = <span class="string">r'C:\Users\Administrator\Desktop\collection.anki2'</span></span><br><span class="line">MEDIA_PATH = <span class="string">r'C:\Users\Administrator\AppData\Roaming\Anki2\账户1\collection.media'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许访问媒体文件</span></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/media/&lt;path:filename&gt;'</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">media</span>(<span class="params">filename</span>):</span></span><br><span class="line">    full_path = os.path.join(MEDIA_PATH, filename)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f"Attempting to access: <span class="subst">{full_path}</span>"</span>)</span><br><span class="line">    <span class="keyword">return</span> send_from_directory(MEDIA_PATH, filename)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">query_database</span>(<span class="params">query, params</span>):</span></span><br><span class="line">    <span class="string">"""执行 SQL 查询并返回结果为 DataFrame"""</span></span><br><span class="line">    conn = sqlite3.connect(DATABASE_PATH)</span><br><span class="line">    df = pd.read_sql_query(query, conn, params=params)</span><br><span class="line">    conn.close()</span><br><span class="line">    <span class="keyword">return</span> df</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/'</span>, methods=[<span class="string">'GET'</span>, <span class="string">'POST'</span>]</span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span>():</span></span><br><span class="line">    results = []</span><br><span class="line">    message = <span class="string">""</span></span><br><span class="line">    <span class="keyword">if</span> request.method == <span class="string">'POST'</span>:</span><br><span class="line">        search_term = request.form.get(<span class="string">'term'</span>, <span class="string">''</span>)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f"Searching for: <span class="subst">{search_term}</span>"</span>)</span><br><span class="line">        <span class="comment"># query = "SELECT id, flds FROM notes WHERE flds LIKE ?"</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 更新查询，获取 flags 字段</span></span><br><span class="line">        <span class="comment"># query = """</span></span><br><span class="line">        <span class="comment">#     SELECT id, flds, flags</span></span><br><span class="line">        <span class="comment">#     FROM notes</span></span><br><span class="line">        <span class="comment">#     WHERE flds LIKE ?</span></span><br><span class="line">        <span class="comment"># """</span></span><br><span class="line"></span><br><span class="line">        query = <span class="string">"""</span></span><br><span class="line"><span class="string">            SELECT id, flds</span></span><br><span class="line"><span class="string">            FROM notes </span></span><br><span class="line"><span class="string">            WHERE flds LIKE ?</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            results_df = query_database(query, (<span class="string">f'%<span class="subst">{search_term}</span>%'</span>,))</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">f"Query results: <span class="subst">{results_df}</span>"</span>)</span><br><span class="line">            <span class="keyword">if</span> results_df.empty:</span><br><span class="line">                message = <span class="string">"未找到相关结果。"</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="keyword">for</span> _, row <span class="keyword">in</span> results_df.iterrows():</span><br><span class="line">                    fields = row[<span class="string">'flds'</span>].split(<span class="string">'\x1f'</span>)</span><br><span class="line">                    <span class="built_in">print</span>(<span class="string">f"Fields content: <span class="subst">{fields}</span>"</span>)</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">for</span> i, field <span class="keyword">in</span> <span class="built_in">enumerate</span>(fields):</span><br><span class="line">                        matches = re.findall(<span class="string">r'src="([^"]+\.(?:jpg|png|gif))"'</span>, field)</span><br><span class="line">                        <span class="keyword">for</span> match <span class="keyword">in</span> matches:</span><br><span class="line">                            img_tag = <span class="string">f' class="image" src="/media/<span class="subst">{match}</span>" alt="Image" '</span></span><br><span class="line">                            field = re.sub(<span class="string">r'src="[^"]*"'</span>, img_tag, field, count=<span class="number">1</span>)</span><br><span class="line">                        fields[i] = field.strip()</span><br><span class="line"></span><br><span class="line">                    <span class="comment"># results.append({'id': row['id'], 'flds': fields})</span></span><br><span class="line"></span><br><span class="line">                    <span class="comment"># 添加 flags 数据</span></span><br><span class="line">                    <span class="comment"># results.append({'id': row['id'], 'flds': fields, 'flags': row['flags']})</span></span><br><span class="line">                    results.append({<span class="string">'id'</span>: row[<span class="string">'id'</span>], <span class="string">'flds'</span>: fields})</span><br><span class="line"></span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">            message = <span class="string">f"查询错误: <span class="subst">{<span class="built_in">str</span>(e)}</span>"</span></span><br><span class="line">            <span class="built_in">print</span>(message)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 使用 render_template 加载 HTML 模板</span></span><br><span class="line">    <span class="keyword">return</span> render_template(<span class="string">'index.html'</span>, results=results, message=message)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/export'</span>, methods=[<span class="string">'GET'</span>]</span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">export_notes</span>():</span></span><br><span class="line">    search_term = request.args.get(<span class="string">'term'</span>, <span class="string">''</span>)</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f"导出请求，搜索词: <span class="subst">{search_term}</span>"</span>)  <span class="comment"># 确认请求是否到达</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># query = """</span></span><br><span class="line">    <span class="comment">#     SELECT id, flds, flags</span></span><br><span class="line">    <span class="comment">#     FROM notes</span></span><br><span class="line">    <span class="comment">#     WHERE flds LIKE ?</span></span><br><span class="line">    <span class="comment"># """</span></span><br><span class="line"></span><br><span class="line">    query = <span class="string">"""</span></span><br><span class="line"><span class="string">        SELECT id, flds</span></span><br><span class="line"><span class="string">        FROM notes </span></span><br><span class="line"><span class="string">        WHERE flds LIKE ?</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        results_df = query_database(query, (<span class="string">f'%<span class="subst">{search_term}</span>%'</span>,))</span><br><span class="line">        temp_file = <span class="string">'exported_notes.csv'</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 使用 utf-8-sig 编码</span></span><br><span class="line">        results_df.to_csv(temp_file, index=<span class="literal">False</span>, encoding=<span class="string">'utf-8-sig'</span>)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> send_file(temp_file, as_attachment=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f"导出错误: <span class="subst">{<span class="built_in">str</span>(e)}</span>"</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="string">"导出失败"</span>, <span class="number">500</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    app.run(host=<span class="string">'0.0.0.0'</span>, port=<span class="number">5000</span>)</span><br></pre></td></tr></tbody></table></figure><h4 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h4><figure class="highlight html"><figcaption><span>index.html</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"zh"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1.0"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Anki 笔记查询<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">type</span>=<span class="string">"text/css"</span> <span class="attr">href</span>=<span class="string">"{{ url_for('static', filename='styles.css') }}"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"static/javascript.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span> <span class="comment">&lt;!-- 引入 JavaScript 文件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Anki 笔记查询<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">method</span>=<span class="string">"post"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"term"</span> <span class="attr">placeholder</span>=<span class="string">"输入搜索关键词"</span> <span class="attr">required</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">id</span>=<span class="string">"searchInput"</span> <span class="attr">placeholder</span>=<span class="string">"搜索内容并导出内容"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">"submit"</span>&gt;</span>搜索<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"exportNotes()"</span>&gt;</span>导出笔记<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h2</span>&gt;</span>查询结果<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"message"</span>&gt;</span>{{ message }}<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>Note ID<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">th</span>&gt;</span>Fields<span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--            &lt;th&gt;flags&lt;/th&gt;--&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">        {% for note in results %}</span><br><span class="line">        <span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>{{ note.id }}<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">td</span>&gt;</span>{{ note.flds | join('<span class="tag">&lt;<span class="name">br</span>&gt;</span>') | safe }}<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">             <span class="comment">&lt;!-- 展示旗帜数据 --&gt;</span></span><br><span class="line"><span class="comment">&lt;!--            &lt;td&gt;{{ note.flags }}&lt;/td&gt;--&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line">        {% endfor %}</span><br><span class="line">    <span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></tbody></table></figure><h4 id="javascript"><a href="#javascript" class="headerlink" title="javascript"></a>javascript</h4><figure class="highlight javascript"><figcaption><span>javascript.js</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">exportNotes</span>(<span class="params"></span>) </span>{</span><br><span class="line">    <span class="keyword">const</span> searchTerm = <span class="built_in">document</span>.getElementById(<span class="string">'searchInput'</span>).value; <span class="comment">// 获取搜索词</span></span><br><span class="line">    <span class="keyword">const</span> url = <span class="string">`/export?term=<span class="subst">${<span class="built_in">encodeURIComponent</span>(searchTerm)}</span>`</span>; <span class="comment">// 构建请求 URL</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">window</span>.location.href = url; <span class="comment">// 直接跳转到 URL 下载文件</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h4><figure class="highlight css"><figcaption><span>styles.css</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* styles.css */</span></span><br><span class="line"><span class="selector-tag">body</span> {</span><br><span class="line">    <span class="attribute">font-family</span>: Arial, sans-serif;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#f9f9f9</span>; <span class="comment">/* 背景颜色 */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">table</span> {</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">border-collapse</span>: collapse; <span class="comment">/* 确保边框合并 */</span></span><br><span class="line">    <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">10px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.1</span>); <span class="comment">/* 添加阴影 */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">th</span>, <span class="selector-tag">td</span> {</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#ddd</span>; <span class="comment">/* 添加边框 */</span></span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">12px</span>; <span class="comment">/* 增加内边距 */</span></span><br><span class="line">    <span class="attribute">text-align</span>: left;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">th</span> {</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#4CAF50</span>; <span class="comment">/* 表头背景色 */</span></span><br><span class="line">    <span class="attribute">color</span>: white; <span class="comment">/* 表头字体颜色 */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">tr</span><span class="selector-pseudo">:nth-child</span>(even) {</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#f2f2f2</span>; <span class="comment">/* 偶数行背景色 */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">tr</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#e0f7fa</span>; <span class="comment">/* 鼠标悬停行的背景色 */</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.message</span> {</span><br><span class="line">    <span class="attribute">color</span>: red;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.image</span> {</span><br><span class="line">    <span class="attribute">max-width</span>: <span class="number">600px</span>; <span class="comment">/* 调整图片尺寸 */</span></span><br><span class="line">    <span class="attribute">max-height</span>: <span class="number">600px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">5px</span>; <span class="comment">/* 圆角 */</span></span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="Anki" scheme="https://coffeelize.top/tags/Anki/"/>
    
    <category term="python" scheme="https://coffeelize.top/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>使用 PyQt 制作简易软件简明笔记</title>
    <link href="https://coffeelize.top/posts/Short-Notes-on-Making-Simple-Software-with-PyQt.html"/>
    <id>https://coffeelize.top/posts/Short-Notes-on-Making-Simple-Software-with-PyQt.html</id>
    <published>2024-08-20T12:30:57.000Z</published>
    <updated>2024-08-21T12:42:27.093Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="缘由"><a href="#缘由" class="headerlink" title="缘由"></a>缘由</h3><p>最近在统计多组数据的重复性，利用到了标准差相关的公式，自然而然想到是使用 Excel 来处理公式。总之，模板是实现了，将公式一步一步拆解，饶了一大圈，发现最后 Excel 本身就内置了求取标准差的函数，还不如不要让我知道这个结果呢，伤心: (</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820204257.png" alt="image.png"></p><p>不过，这也带来了一些思考。自认为自己用 Excel 还算用得多的了，根本没有听过用过这样的内置函数，能不能写个简单的程序，只要将数据往里面一扔，就可以自动出来计算结果呢 —&gt; 于是开始了折腾</p><h3 id="Step-1-搭建环境"><a href="#Step-1-搭建环境" class="headerlink" title="Step 1 搭建环境"></a>Step 1 搭建环境</h3><ul><li>这里选择社区版的 Pycharm，免费，集成开发环境用起来也方便</li><li>程序开发使用的是 PyQt 框架</li></ul><p>刚安装完 Pycharm，会检测系统中是否已经安装好了 python，如果恰好没有安装过，那么根据软件的建议安装即可</p><p>写好的代码中若检测有问题，Pycharm 会在对应的位置进行提示，如一下这段程序，刚安装的 python 肯定是没有 PyQT6 的程序包的，可以通过提示（小红灯泡处，Alt+Enter）进行安装</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820204316.png" alt="image.png"></p><p>新建项目，新建 python 文件，粘贴如下代码进行测试：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> QApplication, QWidget, QVBoxLayout, QPushButton  </span><br><span class="line">  </span><br><span class="line">app = QApplication([])  <span class="comment"># 创建应用程序对象  </span></span><br><span class="line">  </span><br><span class="line">window = QWidget()  <span class="comment"># 创建窗口部件  </span></span><br><span class="line">layout = QVBoxLayout()  <span class="comment"># 创建布局管理器  </span></span><br><span class="line">  </span><br><span class="line">button = QPushButton(<span class="string">"点击我"</span>)  <span class="comment"># 创建按钮  </span></span><br><span class="line">layout.addWidget(button)  <span class="comment"># 将按钮添加到布局管理器中  </span></span><br><span class="line">  </span><br><span class="line">window.setLayout(layout)  <span class="comment"># 设置窗口部件的布局  </span></span><br><span class="line">window.show()  <span class="comment"># 显示窗口  </span></span><br><span class="line">  </span><br><span class="line">app.<span class="built_in">exec</span>()  <span class="comment"># 进入应用程序的主循环</span></span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820205141.png" alt="image.png"></p><p>很好，说明各种环境已经搭建好了！</p><h3 id="Step-2-实现基础功能"><a href="#Step-2-实现基础功能" class="headerlink" title="Step 2 实现基础功能"></a>Step 2 实现基础功能</h3><p>接下来尽管提需求，从开发者的角度出发，一步步给 GPT 进行引导，从易到难，功能从简单到复杂</p><p>例如我开始给 GPT 提需求：</p><blockquote><p>我提供一组数据，点击按钮之后，就可以在一个输出位置输出这组数据的标准差</p></blockquote><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys  </span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np  </span><br><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel, QLineEdit  </span><br><span class="line">  </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MainWindow</span>(<span class="params">QMainWindow</span>):</span>  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        <span class="built_in">super</span>().__init__()  </span><br><span class="line">  </span><br><span class="line">        self.setWindowTitle(<span class="string">"标准差计算器"</span>)  </span><br><span class="line">        self.setGeometry(<span class="number">100</span>, <span class="number">100</span>, <span class="number">400</span>, <span class="number">200</span>)  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 主部件  </span></span><br><span class="line">        self.central_widget = QWidget()  </span><br><span class="line">        self.setCentralWidget(self.central_widget)  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 布局  </span></span><br><span class="line">        self.layout = QVBoxLayout()  </span><br><span class="line">        self.central_widget.setLayout(self.layout)  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 输入框  </span></span><br><span class="line">        self.data_input = QLineEdit()  </span><br><span class="line">        self.data_input.setPlaceholderText(<span class="string">"输入数据，用逗号分隔"</span>)  </span><br><span class="line">        self.layout.addWidget(self.data_input)  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 计算按钮  </span></span><br><span class="line">        self.calculate_button = QPushButton(<span class="string">"计算标准差"</span>)  </span><br><span class="line">        self.calculate_button.clicked.connect(self.calculate_standard_deviation)  </span><br><span class="line">        self.layout.addWidget(self.calculate_button)  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 输出标签  </span></span><br><span class="line">        self.result_label = QLabel(<span class="string">"标准差："</span>)  </span><br><span class="line">        self.layout.addWidget(self.result_label)  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_standard_deviation</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        <span class="comment"># 获取输入数据  </span></span><br><span class="line">        data_text = self.data_input.text()  </span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> data_text:  </span><br><span class="line">            self.result_label.setText(<span class="string">"请先输入数据"</span>)  </span><br><span class="line">            <span class="keyword">return</span>  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 解析数据  </span></span><br><span class="line">        <span class="keyword">try</span>:  </span><br><span class="line">            data = <span class="built_in">list</span>(<span class="built_in">map</span>(<span class="built_in">float</span>, data_text.split(<span class="string">','</span>)))  </span><br><span class="line">        <span class="keyword">except</span> ValueError:  </span><br><span class="line">            self.result_label.setText(<span class="string">"数据格式错误，请输入有效的数字"</span>)  </span><br><span class="line">            <span class="keyword">return</span>  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># 计算标准差  </span></span><br><span class="line">        std_dev = np.std(data)  </span><br><span class="line">        self.result_label.setText(<span class="string">f"标准差：<span class="subst">{std_dev:<span class="number">.2</span>f}</span>"</span>)  </span><br><span class="line">  </span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:  </span><br><span class="line">    app = QApplication(sys.argv)  </span><br><span class="line">    window = MainWindow()  </span><br><span class="line">    window.show()  </span><br><span class="line">    sys.exit(app.<span class="built_in">exec</span>())</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820205448.png" alt="image.png"></p><p>好了，手动输入几组数据，确实能够计算出来标准差了，不过我们的数据来自 Excel，而且用逗号分隔数据的方式也不方便。于是就有了如下需求：</p><blockquote><p>但是，你知道的，我的输入数据一般从 excel 中复制过来的，这种用逗号分隔数字的方式让我在输入的时候非常麻烦</p></blockquote><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> QApplication, QWidget, QVBoxLayout, QPushButton, QPlainTextEdit, QLabel</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DataProcessingApp</span>(<span class="params">QWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 设置窗口标题和尺寸</span></span><br><span class="line">        self.setWindowTitle(<span class="string">"数据处理应用"</span>)</span><br><span class="line">        self.setGeometry(<span class="number">100</span>, <span class="number">100</span>, <span class="number">400</span>, <span class="number">300</span>)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 创建布局和组件</span></span><br><span class="line">        layout = QVBoxLayout()</span><br><span class="line"></span><br><span class="line">        self.text_edit = QPlainTextEdit(self)</span><br><span class="line">        self.text_edit.setPlaceholderText(<span class="string">"在这里粘贴数据..."</span>)</span><br><span class="line">        layout.addWidget(self.text_edit)</span><br><span class="line"></span><br><span class="line">        self.calculate_button = QPushButton(<span class="string">"计算标准差"</span>, self)</span><br><span class="line">        self.calculate_button.clicked.connect(self.calculate_std_dev)</span><br><span class="line">        layout.addWidget(self.calculate_button)</span><br><span class="line"></span><br><span class="line">        self.result_label = QLabel(<span class="string">"标准差："</span>, self)</span><br><span class="line">        layout.addWidget(self.result_label)</span><br><span class="line"></span><br><span class="line">        self.setLayout(layout)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_std_dev</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 获取文本内容</span></span><br><span class="line">        text = self.text_edit.toPlainText()</span><br><span class="line">        </span><br><span class="line">        <span class="comment"># 处理文本数据</span></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="comment"># 将文本数据按行分隔，然后按空格或制表符分隔</span></span><br><span class="line">            data = [<span class="built_in">float</span>(num) <span class="keyword">for</span> line <span class="keyword">in</span> text.splitlines() <span class="keyword">for</span> num <span class="keyword">in</span> line.split()]</span><br><span class="line">            <span class="keyword">if</span> data:</span><br><span class="line">                <span class="comment"># 计算标准差</span></span><br><span class="line">                std_dev = np.std(data)</span><br><span class="line">                self.result_label.setText(<span class="string">f"标准差：<span class="subst">{std_dev:<span class="number">.2</span>f}</span>"</span>)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                self.result_label.setText(<span class="string">"标准差：无效数据"</span>)</span><br><span class="line">        <span class="keyword">except</span> ValueError:</span><br><span class="line">            self.result_label.setText(<span class="string">"标准差：数据格式错误"</span>)</span><br><span class="line"></span><br><span class="line">app = QApplication([])</span><br><span class="line">window = DataProcessingApp()</span><br><span class="line">window.show()</span><br><span class="line">app.<span class="built_in">exec</span>()</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820205734.png" alt="image.png"></p><p>以上这组数据就是直接从 Excel 粘贴进去的。看来功能 GPT 是帮我们实现了</p><h3 id="Step-3-完善程序"><a href="#Step-3-完善程序" class="headerlink" title="Step 3 完善程序"></a>Step 3 完善程序</h3><p>接下来按照上面的步骤，进一步提需求，进一步完善程序代码<br>例如，可以增加一些数据清洗、数据输入验证、错处处理、历史记录、导出数据等功能<br>也可以对程序进行拆分，不同功能的代码写到不同的 py 文件中</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820210219.png" alt="image.png"></p><p>当前的程序结构为</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">data_processor/</span><br><span class="line">│</span><br><span class="line">├── main.py</span><br><span class="line">├── ui.py</span><br><span class="line">├── processor.py</span><br><span class="line">└── utils.py</span><br></pre></td></tr></tbody></table></figure><h4 id="主程序"><a href="#主程序" class="headerlink" title="主程序"></a>主程序</h4><figure class="highlight python"><figcaption><span>main.py</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> QApplication</span><br><span class="line"><span class="keyword">from</span> ui <span class="keyword">import</span> DataProcessorApp</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line">    app = QApplication(sys.argv)</span><br><span class="line">    processor = DataProcessorApp()</span><br><span class="line">    processor.show()</span><br><span class="line">    sys.exit(app.<span class="built_in">exec</span>())</span><br></pre></td></tr></tbody></table></figure><h4 id="UI-界面"><a href="#UI-界面" class="headerlink" title="UI 界面"></a>UI 界面</h4><figure class="highlight python"><figcaption><span>ui.py</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PyQt6.QtWidgets <span class="keyword">import</span> QWidget, QVBoxLayout, QPushButton, QTextEdit, QLabel  </span><br><span class="line"><span class="keyword">from</span> PyQt6.QtGui <span class="keyword">import</span> QFont, QColor  </span><br><span class="line"><span class="keyword">from</span> PyQt6.QtCore <span class="keyword">import</span> Qt  </span><br><span class="line"><span class="keyword">from</span> PyQt6.QtGui <span class="keyword">import</span> QPalette  </span><br><span class="line"><span class="keyword">from</span> processor <span class="keyword">import</span> DataProcessor  </span><br><span class="line">  </span><br><span class="line">  </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DataProcessorApp</span>(<span class="params">QWidget</span>):</span>  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        <span class="built_in">super</span>().__init__()  </span><br><span class="line">        self.processor = DataProcessor()  </span><br><span class="line">        self.init_ui()  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">init_ui</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        <span class="comment"># Set the overall layout and style  </span></span><br><span class="line">        layout = QVBoxLayout()  </span><br><span class="line">        self.setStyleSheet(<span class="string">"background-color: #f0f0f0;"</span>)  </span><br><span class="line">        self.setPalette(QPalette(QColor(<span class="string">'#f0f0f0'</span>)))  </span><br><span class="line">  </span><br><span class="line">        <span class="comment"># Create and style widgets  </span></span><br><span class="line">        self.input_text = QTextEdit(self)  </span><br><span class="line">        self.input_text.setPlaceholderText(<span class="string">"在这里粘贴数据，每行一个数字"</span>)  </span><br><span class="line">        self.input_text.setStyleSheet(<span class="string">"font-size: 14px; padding: 10px; border: 1px solid #ccc;"</span>)  </span><br><span class="line">        layout.addWidget(self.input_text)  </span><br><span class="line">  </span><br><span class="line">        self.mean_label = QLabel(<span class="string">"平均值："</span>, self)  </span><br><span class="line">        self.mean_label.setStyleSheet(<span class="string">"font-size: 16px; color: #333;"</span>)  </span><br><span class="line">        layout.addWidget(self.mean_label)  </span><br><span class="line">  </span><br><span class="line">        self.variance_label = QLabel(<span class="string">"方差："</span>, self)  </span><br><span class="line">        self.variance_label.setStyleSheet(<span class="string">"font-size: 16px; color: #333;"</span>)  </span><br><span class="line">        layout.addWidget(self.variance_label)  </span><br><span class="line">  </span><br><span class="line">        self.std_dev_label = QLabel(<span class="string">"标准差："</span>, self)  </span><br><span class="line">        self.std_dev_label.setStyleSheet(<span class="string">"font-size: 16px; color: #333;"</span>)  </span><br><span class="line">        layout.addWidget(self.std_dev_label)  </span><br><span class="line">  </span><br><span class="line">        self.reliability_label = QLabel(<span class="string">"重复性："</span>, self)  </span><br><span class="line">        self.reliability_label.setStyleSheet(<span class="string">"font-size: 16px; color: #333;"</span>)  </span><br><span class="line">        layout.addWidget(self.reliability_label)  </span><br><span class="line">  </span><br><span class="line">        process_button = QPushButton(<span class="string">"计算标准差"</span>, self)  </span><br><span class="line">        process_button.setStyleSheet(  </span><br><span class="line">            <span class="string">"background-color: #4CAF50; color: white; font-size: 14px; padding: 10px; border: none; border-radius: 5px;"</span>)  </span><br><span class="line">        process_button.clicked.connect(self.calculate_std_dev)  </span><br><span class="line">        layout.addWidget(process_button)  </span><br><span class="line">  </span><br><span class="line">        reliability_button = QPushButton(<span class="string">"计算重复性"</span>, self)  </span><br><span class="line">        reliability_button.setStyleSheet(  </span><br><span class="line">            <span class="string">"background-color: #2196F3; color: white; font-size: 14px; padding: 10px; border: none; border-radius: 5px;"</span>)  </span><br><span class="line">        reliability_button.clicked.connect(self.calculate_reliability)  </span><br><span class="line">        layout.addWidget(reliability_button)  </span><br><span class="line">  </span><br><span class="line">        self.history_text = QTextEdit(self)  </span><br><span class="line">        self.history_text.setPlaceholderText(<span class="string">"历史记录"</span>)  </span><br><span class="line">        self.history_text.setReadOnly(<span class="literal">True</span>)  </span><br><span class="line">        self.history_text.setStyleSheet(<span class="string">"font-size: 14px; padding: 10px; border: 1px solid #ccc;"</span>)  </span><br><span class="line">        layout.addWidget(self.history_text)  </span><br><span class="line">  </span><br><span class="line">        self.setLayout(layout)  </span><br><span class="line">        self.setWindowTitle(<span class="string">"数据处理程序"</span>)  </span><br><span class="line">        self.setGeometry(<span class="number">100</span>, <span class="number">100</span>, <span class="number">500</span>, <span class="number">400</span>)  </span><br><span class="line">        self.setFont(QFont(<span class="string">'Arial'</span>, <span class="number">12</span>))  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_std_dev</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        data = self.input_text.toPlainText().strip()  </span><br><span class="line">        <span class="keyword">try</span>:  </span><br><span class="line">            numbers = [<span class="built_in">float</span>(x) <span class="keyword">for</span> x <span class="keyword">in</span> data.split() <span class="keyword">if</span> x.replace(<span class="string">'.'</span>, <span class="string">''</span>, <span class="number">1</span>).isdigit()]  </span><br><span class="line">            <span class="keyword">if</span> numbers:  </span><br><span class="line">                std_dev = self.processor.calculate_std_dev(numbers)  </span><br><span class="line">                mean, variance, std_dev, _ = self.processor.calculate_reliability(numbers)  </span><br><span class="line">                self.mean_label.setText(<span class="string">f"平均值：<span class="subst">{mean:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">                self.variance_label.setText(<span class="string">f"方差：<span class="subst">{variance:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">                self.std_dev_label.setText(<span class="string">f"标准差：<span class="subst">{std_dev:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">            <span class="keyword">else</span>:  </span><br><span class="line">                self.std_dev_label.setText(<span class="string">"标准差：无效数据"</span>)  </span><br><span class="line">                self.mean_label.setText(<span class="string">"平均值：无效数据"</span>)  </span><br><span class="line">                self.variance_label.setText(<span class="string">"方差：无效数据"</span>)  </span><br><span class="line">            history = self.history_text.toPlainText()  </span><br><span class="line">            new_entry = <span class="string">f"数据：<span class="subst">{<span class="string">', '</span>.join(<span class="built_in">map</span>(<span class="built_in">str</span>, numbers))}</span> | 标准差：<span class="subst">{std_dev:<span class="number">.6</span>f}</span> | 平均值：<span class="subst">{mean:<span class="number">.6</span>f}</span> | 方差：<span class="subst">{variance:<span class="number">.6</span>f}</span>\n"</span>  </span><br><span class="line">            self.history_text.setText(history + new_entry)  </span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> e:  </span><br><span class="line">            self.std_dev_label.setText(<span class="string">f"错误：<span class="subst">{e}</span>"</span>)  </span><br><span class="line">            self.mean_label.setText(<span class="string">"平均值：无效数据"</span>)  </span><br><span class="line">            self.variance_label.setText(<span class="string">"方差：无效数据"</span>)  </span><br><span class="line">  </span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_reliability</span>(<span class="params">self</span>):</span>  </span><br><span class="line">        data = self.input_text.toPlainText().strip()  </span><br><span class="line">        <span class="keyword">try</span>:  </span><br><span class="line">            numbers = [<span class="built_in">float</span>(x) <span class="keyword">for</span> x <span class="keyword">in</span> data.split() <span class="keyword">if</span> x.replace(<span class="string">'.'</span>, <span class="string">''</span>, <span class="number">1</span>).isdigit()]  </span><br><span class="line">            <span class="keyword">if</span> numbers:  </span><br><span class="line">                mean, variance, std_dev, reliability = self.processor.calculate_reliability(numbers)  </span><br><span class="line">                self.mean_label.setText(<span class="string">f"平均值：<span class="subst">{mean:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">                self.variance_label.setText(<span class="string">f"方差：<span class="subst">{variance:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">                self.std_dev_label.setText(<span class="string">f"标准差：<span class="subst">{std_dev:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">                self.reliability_label.setText(<span class="string">f"重复性：<span class="subst">{reliability:<span class="number">.6</span>f}</span>"</span>)  </span><br><span class="line">            <span class="keyword">else</span>:  </span><br><span class="line">                self.reliability_label.setText(<span class="string">"重复性：无效数据"</span>)  </span><br><span class="line">                self.mean_label.setText(<span class="string">"平均值：无效数据"</span>)  </span><br><span class="line">                self.variance_label.setText(<span class="string">"方差：无效数据"</span>)  </span><br><span class="line">                self.std_dev_label.setText(<span class="string">"标准差：无效数据"</span>)  </span><br><span class="line">            history = self.history_text.toPlainText()  </span><br><span class="line">            new_entry = <span class="string">f"数据：<span class="subst">{<span class="string">', '</span>.join(<span class="built_in">map</span>(<span class="built_in">str</span>, numbers))}</span> | 标准差：<span class="subst">{std_dev:<span class="number">.6</span>f}</span> | 重复性：<span class="subst">{reliability:<span class="number">.6</span>f}</span> | 平均值：<span class="subst">{mean:<span class="number">.6</span>f}</span> | 方差：<span class="subst">{variance:<span class="number">.6</span>f}</span>\n"</span>  </span><br><span class="line">            self.history_text.setText(history + new_entry)  </span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> e:  </span><br><span class="line">            self.reliability_label.setText(<span class="string">f"错误：<span class="subst">{e}</span>"</span>)  </span><br><span class="line">            self.mean_label.setText(<span class="string">"平均值：无效数据"</span>)  </span><br><span class="line">            self.variance_label.setText(<span class="string">"方差：无效数据"</span>)  </span><br><span class="line">            self.std_dev_label.setText(<span class="string">"标准差：无效数据"</span>)</span><br></pre></td></tr></tbody></table></figure><h4 id="数据处理"><a href="#数据处理" class="headerlink" title="数据处理"></a>数据处理</h4><figure class="highlight python"><figcaption><span>processor.py</span></figcaption><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DataProcessor</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_std_dev</span>(<span class="params">self, numbers</span>):</span></span><br><span class="line">        <span class="keyword">return</span> np.std(numbers, ddof=<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">calculate_reliability</span>(<span class="params">self, numbers</span>):</span></span><br><span class="line">        mean = np.mean(numbers)</span><br><span class="line">        variance = np.var(numbers, ddof=<span class="number">1</span>)</span><br><span class="line">        std_dev = np.sqrt(variance)</span><br><span class="line">        reliability = std_dev / mean</span><br><span class="line">        <span class="keyword">return</span> mean, variance, std_dev, reliability</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><h3 id="Step-4-打包程序"><a href="#Step-4-打包程序" class="headerlink" title="Step 4 打包程序"></a>Step 4 打包程序</h3><p>想要将整个程序打包成 exe 文件，这样方便在没有 python 环境时依然可以运行，步骤如下：</p><ul><li>安装 PyInstaller 包（可以直接在 powershell 中安装）</li><li>使用 PyInstaller 打包脚本</li></ul><p>1、在 PowerShell 中，运行如下命令</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install pyinstaller</span><br></pre></td></tr></tbody></table></figure><p>注意：前面已经安装了 python 程序，应该是可以使用 pip 命令了的。可输入 <code>pip --version</code> 命令查看。若该命令无法使用，很可能是没有将 python 解释器添加到环境变量中，可进行如下操作：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\Administrator\AppData\Local\Programs\Python\Python312\</span><br><span class="line">C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Scripts\</span><br></pre></td></tr></tbody></table></figure><p>这里的路径请替换为实际安装 Python 的路径</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820211551.png" alt="image.png"></p><p>2、运行 pyinstaller 命令打包程序</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pyinstaller --onefile --windowed your_script.py</span><br></pre></td></tr></tbody></table></figure><ul><li><code>--onefile</code>：将所有内容打包成一个单独的 <code>.exe </code> 文件。</li><li><code>--windowed</code>：用于创建一个没有命令行窗口的图形界面应用。</li></ul><p>打包完成后，会生成几个文件夹：</p><ul><li><code>dist</code> 中包含生成的 exe 文件</li><li><code>build</code> 中包含构建过程中的临时文件，可以删除。</li><li><code>your_script.spec</code> 文件是 PyInstaller 的配置文件，可以根据需要进行修改。</li></ul><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240820211643.png" alt="image.png"></p><p><img data-src="https://s2.loli.net/2024/08/20/FvgUAH9DrSljCQ7.gif" alt=".gif"></p><p>恭喜你，得到了一款简易的小程序：）</p><h3 id="续"><a href="#续" class="headerlink" title="续"></a>续</h3><p>明明程序实现的功能很简单，为什么生成的程序还那么大呢，例如生成上面的这个 exe 文件就有 50M。因为软件将一些必要的程序包（如 numpy 模块）都打包进去了，若之后再增加一些计算相关的各种功能进去，程序体积可能也只会大一丢丢吧</p><p>另外，打包时如何优化资源，排除掉一些不必要的模块还值得学学。不过，尽管文件体积大点，功能总算是实现了，还是蛮有成就感的</p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="PyQt" scheme="https://coffeelize.top/tags/PyQt/"/>
    
    <category term="excel" scheme="https://coffeelize.top/tags/excel/"/>
    
  </entry>
  
  <entry>
    <title>制作 Anki 插件简明笔记</title>
    <link href="https://coffeelize.top/posts/Short-Notes-on-Making-Anki-Plugins.html"/>
    <id>https://coffeelize.top/posts/Short-Notes-on-Making-Anki-Plugins.html</id>
    <published>2024-08-17T07:37:26.000Z</published>
    <updated>2024-08-17T08:12:52.804Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="插件想法"><a href="#插件想法" class="headerlink" title="插件想法"></a>插件想法</h3><p>想法来自于 Anki 插件：<a href="https://ankiweb.net/shared/info/1915225457">ankiweb.net/shared/info/1915225457</a>，没想到 Anki 程序内部还能内嵌浏览器，不可思议</p><p>换在从前，想想自己那么菜的技术也就过了，可是目前有了 GPT 的加持，事情就变得不可思议了。当然，想要开发一款体验性能都好的插件，一个可称之为 <code>项目</code> 的插件，GPT 目前还是不太行的，下面为使用 GPT 辅助开发的两个简单 Anki 插件</p><h3 id="插件目录"><a href="#插件目录" class="headerlink" title="插件目录"></a>插件目录</h3><p>打开 Anki，快捷键 <code>Ctrl+Shift+A</code> 可弹出插件管理器，点击 <code>查看文件</code> 可以跳转到 Anki 插件的安装目录</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240817153950.png" alt="image.png"></p><p>例如我的 Anki 插件文件路径为：<code>C:\Users\Administrator\AppData\Roaming\Anki2\addons21</code></p><h3 id="创建插件"><a href="#创建插件" class="headerlink" title="创建插件"></a>创建插件</h3><p>新建文件夹，例如 <code>BrowserPlugin</code>，在文件夹中新建 <code>__init__.py</code> 文件，之后在该 python 文件中编辑代码即可。</p><p>PS：每次修改代码之后，需重启 Anki 以重新加载插件，插件为自动加载方式</p><p>ANKI 插件的完整生成过程可参考与 GPT 的对话：<a href="https://chatgpt.com/share/57cfc0cc-8f0b-4774-8c69-f83dda3f1e14">ChatGPT - 开发 Anki 插件</a>. </p><p>我只负责引导和给出调试报错信息，代码全程由 GPT 负责生成，代码如下：</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240817161238.png" alt="image.png"></p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> aqt <span class="keyword">import</span> mw</span><br><span class="line"><span class="keyword">from</span> aqt.qt <span class="keyword">import</span> QAction, QMenu</span><br><span class="line"><span class="keyword">from</span> PyQt6.QtCore <span class="keyword">import</span> Qt</span><br><span class="line"><span class="keyword">import</span> webbrowser</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">onGoogleSearch</span>():</span></span><br><span class="line">    <span class="comment"># 获取当前选中的文本</span></span><br><span class="line">    selected_text = mw.web.selectedText()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> selected_text:</span><br><span class="line">        <span class="comment"># 使用浏览器打开Google搜索页面</span></span><br><span class="line">        webbrowser.<span class="built_in">open</span>(<span class="string">f"https://www.google.com/search?q=<span class="subst">{selected_text}</span>"</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">showContextMenu</span>(<span class="params">point</span>):</span></span><br><span class="line">    menu = QMenu()</span><br><span class="line">    </span><br><span class="line">    selected_text = mw.web.selectedText()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> selected_text:</span><br><span class="line">        action = QAction(<span class="string">"Google搜索"</span>, mw)</span><br><span class="line">        action.triggered.connect(onGoogleSearch)</span><br><span class="line">        menu.addAction(action)</span><br><span class="line">    </span><br><span class="line">    menu.<span class="built_in">exec</span>(mw.web.mapToGlobal(point))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">setup_menu</span>():</span></span><br><span class="line">    mw.web.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)</span><br><span class="line">    mw.web.customContextMenuRequested.connect(showContextMenu)</span><br><span class="line"></span><br><span class="line">setup_menu()</span><br></pre></td></tr></tbody></table></figure><p>重启 Anki 之后（插件会自动加载），选中文字右键，即可弹出 Google 搜索菜单项，点击即可使用外部浏览器对选中的文字进行搜索，效果如下：</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240817154714.png" alt="image.png"></p><h3 id="进一步完善插件"><a href="#进一步完善插件" class="headerlink" title="进一步完善插件"></a>进一步完善插件</h3><p>如上所述，搜索时使用外部浏览器进行搜索，能否在 Anki 程序中内嵌浏览器呢 —&gt; 接下来还是通过 GPT 的辅助，完成初步的想法，完整示例代码如下：</p><figure class="highlight python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> aqt <span class="keyword">import</span> mw</span><br><span class="line"><span class="keyword">from</span> aqt.qt <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">from</span> PyQt6.QtWebEngineWidgets <span class="keyword">import</span> QWebEngineView</span><br><span class="line"><span class="keyword">from</span> PyQt6.QtCore <span class="keyword">import</span> QUrl, Qt</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BrowserDockWidget</span>(<span class="params">QDockWidget</span>):</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span>(<span class="params">self, parent=<span class="literal">None</span></span>):</span></span><br><span class="line">        <span class="built_in">super</span>().__init__(<span class="string">"内置浏览器"</span>, parent)</span><br><span class="line">        self.browser = QWebEngineView()</span><br><span class="line">        self.setWidget(self.browser)</span><br><span class="line">        self.setup_browser_settings()</span><br><span class="line">        self.browser.setUrl(QUrl(<span class="string">"https://www.google.com"</span>))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setup_browser_settings</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="comment"># 确保启用 JavaScript 和其他必要的功能</span></span><br><span class="line">        settings = self.browser.settings()</span><br><span class="line">        settings.setAttribute(QWebEngineSettings.WebAttribute.JavascriptEnabled, <span class="literal">True</span>)</span><br><span class="line">        settings.setAttribute(QWebEngineSettings.WebAttribute.PluginsEnabled, <span class="literal">True</span>)</span><br><span class="line">        settings.setAttribute(QWebEngineSettings.WebAttribute.LocalStorageEnabled, <span class="literal">True</span>)</span><br><span class="line">        settings.setAttribute(QWebEngineSettings.WebAttribute.DnsPrefetchEnabled, <span class="literal">True</span>)</span><br><span class="line">        settings.setAttribute(QWebEngineSettings.WebAttribute.AutoLoadImages, <span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">search</span>(<span class="params">self, query</span>):</span></span><br><span class="line">        self.browser.setUrl(QUrl(<span class="string">f"https://www.google.com/search?q=<span class="subst">{query}</span>"</span>))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">show_browser_dock_widget</span>():</span></span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> <span class="built_in">hasattr</span>(mw, <span class="string">'browser_dock'</span>):</span><br><span class="line">        mw.browser_dock = BrowserDockWidget(mw)</span><br><span class="line">        mw.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, mw.browser_dock)</span><br><span class="line">    mw.browser_dock.show()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">on_search_google</span>():</span></span><br><span class="line">    selected_text = mw.web.selectedText()</span><br><span class="line">    <span class="keyword">if</span> selected_text:</span><br><span class="line">        show_browser_dock_widget()</span><br><span class="line">        mw.browser_dock.search(selected_text)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">context_menu_event</span>(<span class="params">point</span>):</span></span><br><span class="line">    menu = QMenu(mw)</span><br><span class="line">    menu.addAction(<span class="string">"Google搜索"</span>, on_search_google)</span><br><span class="line">    menu.<span class="built_in">exec</span>(mw.web.mapToGlobal(point))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">add_search_context_menu</span>():</span></span><br><span class="line">    mw.web.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)</span><br><span class="line">    mw.web.customContextMenuRequested.connect(context_menu_event)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加右键菜单项</span></span><br><span class="line">add_search_context_menu()</span><br></pre></td></tr></tbody></table></figure><p>浏览器右上角的几个按钮可以对内置浏览器进行关闭，拖动还可以自定义浏览器在 Anki 程序中的位置，展示效果如下：</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240817155910.png" alt="image.png"></p><p><img data-src="https://s2.loli.net/2024/08/17/Qg1zZeX9WCsP5kf.gif" alt="Anki.gif"></p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="Anki" scheme="https://coffeelize.top/tags/Anki/"/>
    
  </entry>
  
  <entry>
    <title>LaTeX 图片背景 eso-pic 宏包</title>
    <link href="https://coffeelize.top/posts/LaTeX-picture-background-eso-pic-macro-package.html"/>
    <id>https://coffeelize.top/posts/LaTeX-picture-background-eso-pic-macro-package.html</id>
    <published>2024-06-21T08:26:58.000Z</published>
    <updated>2024-06-22T10:18:55.826Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ul><li>Ctan.org： <a href="https://ctan.org/pkg/eso-pic">eso-pic – Add picture commands (or backgrounds) to every page</a></li><li> 英文 PDF 手册： <a href="https://mirror-hk.koddos.net/CTAN/macros/latex/contrib/eso-pic/eso-pic.pdf">eso-pic 宏包帮助文档</a></li><li>宏包简要说明：This package makes it easy to add some picture commands to every page at absolute positions</li></ul><h3 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h3><ul><li><code>\AddToShipoutPictureBG</code>：为每一页添加背景</li><li><code>\AddToShipoutPictureBG*</code>：仅为当前页面添加背景</li><li><code>\AddToShipoutPictureFG</code>：类似于 BG，但只作用于文档内容部分</li></ul><p>一些预定于好的位置命令</p><ul><li>AtPageUpperLeft</li><li>AtPageLowerLeft</li><li>AtPageCenter</li><li>AtTextUpperLeft</li><li>AtTextLowerLeft</li><li>AtTextCenter</li><li>AtStockUpperLeft</li><li>AtStockLowerLeft</li><li>AtStockCenter</li></ul><h3 id="案例分析"><a href="#案例分析" class="headerlink" title="案例分析"></a>案例分析</h3><figure class="highlight tex"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">\documentclass</span>{ctexart}</span><br><span class="line"><span class="keyword">\usepackage</span>{graphicx}</span><br><span class="line"><span class="keyword">\usepackage</span>{zhlipsum}</span><br><span class="line"><span class="keyword">\usepackage</span>{eso-pic}</span><br><span class="line"><span class="keyword">\begin</span>{document}</span><br><span class="line"><span class="keyword">\zhlipsum</span>[1-3]</span><br><span class="line"><span class="keyword">\clearpage</span></span><br><span class="line"><span class="keyword">\AddToShipoutPictureBG</span>{</span><br><span class="line"><span class="keyword">\includegraphics</span>[width=<span class="keyword">\paperwidth</span>,height=<span class="keyword">\paperheight</span>]{example-image-duck}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">\clearpage</span></span><br><span class="line"><span class="keyword">\zhlipsum</span>[1]</span><br><span class="line"><span class="keyword">\clearpage</span></span><br><span class="line"><span class="keyword">\zhlipsum</span>[1]</span><br><span class="line"><span class="keyword">\section</span>{第一部分}</span><br><span class="line"></span><br><span class="line"><span class="keyword">\end</span>{document}</span><br></pre></td></tr></tbody></table></figure><p>插入长宽和当前页面长宽一致的鸭子的背景图片</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240621162756.png" alt="image.png"></p><p>如果我们有比较好的背景图片，比如四角带有阴影的 png 图片或者设计好的图片，那么使用该宏包还是挺有效果的</p><h3 id="部分说明"><a href="#部分说明" class="headerlink" title="部分说明"></a>部分说明</h3><figure class="highlight tex"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">width=<span class="keyword">\paperwidth</span>,height=<span class="keyword">\paperheight</span></span><br></pre></td></tr></tbody></table></figure><p>表示图片的长宽和页面的长宽一致，将图片强制拉伸至页面长宽</p><figure class="highlight tex"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">example-image-duck</span><br><span class="line">example-image-a</span><br><span class="line">example-grid-100x100bp</span><br></pre></td></tr></tbody></table></figure><p>这几个图片名称经常用于插入示范图片，分别代表 <code>鸭子</code>、<code>字母A</code> 和 <code>长宽为10个单元格的网格表</code> </p><p>注意使用 graphics 宏包（正常应为 graphicx 宏包）插入 includegraphics 命令时 texstudio 不会出现红色背景提示，但是编译出来老是报错 <code>\end{document}</code></p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240621163115.png" alt="image.png"></p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    <category term="LaTeX" scheme="https://coffeelize.top/categories/LaTeX/"/>
    
    
    <category term="Latex" scheme="https://coffeelize.top/tags/Latex/"/>
    
    <category term="image" scheme="https://coffeelize.top/tags/image/"/>
    
  </entry>
  
  <entry>
    <title>残余应力</title>
    <link href="https://coffeelize.top/posts/Residual-stresses.html"/>
    <id>https://coffeelize.top/posts/Residual-stresses.html</id>
    <published>2024-06-18T10:17:13.000Z</published>
    <updated>2024-06-22T09:24:21.007Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ul><li><a href="https://www.bilibili.com/video/BV16w411G7nJ/?spm_id_from=333.337.search-card.all.click&amp;vd_source=3ae7ae95fa254383ab9ae83f75abd29d">残余应力如何消除？说一说残余应力消除技术_哔哩哔哩_bilibili</a></li><li><a href="https://www.bilibili.com/video/BV1yc411o7aH/?spm_id_from=333.337.search-card.all.click&amp;vd_source=3ae7ae95fa254383ab9ae83f75abd29d">简述什么是残余内应力_哔哩哔哩_bilibili</a></li></ul><h3 id="残余应力的概念"><a href="#残余应力的概念" class="headerlink" title="残余应力的概念"></a>残余应力的概念</h3><p>在无外力或外力矩的作用下，存在于材料内部，且达到自平衡状态的力。</p><p>从微观上看，残余应力的本质是晶格畸变，以 “畸变能” 到形式存在于材料内部。</p><p>这些能量不会随着加工过程中能量的交换或材料的变形与剥离而全部消散掉，其中一部分转换为势能，以残余应力及形变的形式存储在介质中。<br>一旦原有的平衡被打破，上述势能中的一部分转化为残余应力作用下发生形变所作的功，使工件整体进入新的平衡，从而造成各加工环节中由残余应力引起的不同程度的加工变形。</p><h3 id="残余应力的影响"><a href="#残余应力的影响" class="headerlink" title="残余应力的影响"></a>残余应力的影响</h3><p>残余应力是零件质量性能的关键指标，直接影响零件的加工精度、尺寸稳定性、腐蚀开裂、疲劳强度以及使用寿命等性能。</p><p>—&gt; 为使零件达到良好的质量状态，应对其残余应力加以控制和利用：</p><ul><li>对过高的残余应力进行消除；</li><li>对不均匀的残余应力进行均化处理；</li><li>对有特殊要求的零件进行表面强化，引入压应力。</li></ul><h3 id="残余应力消除的主要方法"><a href="#残余应力消除的主要方法" class="headerlink" title="残余应力消除的主要方法"></a>残余应力消除的主要方法</h3><h4 id="自然实效"><a href="#自然实效" class="headerlink" title="自然实效"></a>自然实效</h4><p>把工件露天放置于室外，经过几个月至几年的风吹、日晒、雨淋和季节的温度变化，给工件多次造成反复的温度应力，促使残余应力发生松弛，获得稳定的状态。</p><ul><li>特点：处理简单、进程缓慢</li><li>应用：<ul><li>结构或尺寸特殊的工件或原材料应用多</li><li>在加工过程中也有应用（装夹下，减少卸除夹具后的变形量）</li></ul></li></ul><h4 id="热实效"><a href="#热实效" class="headerlink" title="热实效"></a>热实效</h4><p>热实效是把工件放进热实效炉中进行热处理，由室温缓慢均匀加热至一定温度，保温一段时间后，再严格控制降温速度最终出炉。</p><p>热实效主要是利用材料在高温状态下，原子活动能力增强，而材料的屈服强度降低的特点，促进位错开动和原子回复，使得晶格畸变得到消除，残余应力得到消除。</p><p>典型应用为去应力退火，将材料加热至再结晶温度以下，保温一定时间后再缓慢冷却，以达到消除材料内部残余内应力的效果。（注意：材料热实效的工艺参数，可通过相关材料手册的热处理制度查得。由于材料成分、加工方法、内应力大小和分布不同，去应力退火的温度范围很广）</p><p>应用：热锻轧、铸造、各种冷变形加工、切削、焊接、热处理，甚至零部件装配后，都可以在不改变组织状态、保留冷作、热作或者表面硬化的条件下，加热到一定温度去除构件的内应力。</p><ul><li>优点：<ul><li>对于大多数材料能取得较好的效果，工程上有广泛、成熟的应用</li></ul></li><li>缺点：<ul><li>去应力效果与温度相关性大，温度影响材料组织和力学性能，处理过程中可能产生：氧化烧损、相变析出、热变形等情况</li><li>对于大型构件难以适用</li><li>能耗高</li></ul></li></ul><h4 id="振动时效"><a href="#振动时效" class="headerlink" title="振动时效"></a>振动时效</h4><p>工程材料常用的一种消除内部残余应力的方法，通过振动，使材料发生微量的塑性变形，从而使材料内部的应力得以松弛。分为亚共振实效、模态宽屏实效、频谱谐波实效、频谱谐波定位实效等方式。</p><p>以振动的形式给工件施加动应力，当动应力与工件残余应力叠加后，达到或超过材料的屈服极限时，工件发生微观或宏观塑性变形，从而使工件内部的残余应力得以松弛。</p><p>振动时效能够在一些场景下取代热实效。同时由于振动时效的机理与热实效不同，因此它也能够在热实效之后再次应用，并达到进一步消除残余应力的效果。</p><h4 id="其他方法"><a href="#其他方法" class="headerlink" title="其他方法"></a>其他方法</h4><ul><li>机械拉伸发</li><li>爆炸法</li><li>超声冲击法</li></ul><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/20240618181955.png" alt="image.png"></p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="mechanic" scheme="https://coffeelize.top/tags/mechanic/"/>
    
  </entry>
  
  <entry>
    <title>文件树目录</title>
    <link href="https://coffeelize.top/posts/Creating-a-file-tree-directory.html"/>
    <id>https://coffeelize.top/posts/Creating-a-file-tree-directory.html</id>
    <published>2024-06-16T06:20:44.000Z</published>
    <updated>2024-07-03T08:51:40.847Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>新建文本文件，将以下两种方式中的任意一种粘贴到文本中，并保存为 <code>bat</code> 格式双击运行即可</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">echo off &amp; color 0A</span><br><span class="line">echo 当前目录："%cd%" &gt;fileTree.txt</span><br><span class="line">tree /f &gt;&gt;fileTree.txt</span><br><span class="line">echo 目录树已生成，按任意键查看。</span><br><span class="line">pause&gt;nul</span><br><span class="line">start fileTree.txt</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tree /f &gt; tree_output.txt</span><br></pre></td></tr></tbody></table></figure><ul><li>如果只想输出文件夹信息，加 <code>/a</code> 参数</li><li>如果想输出文件夹下的文件名，加 <code>/f</code> 参数</li></ul><hr><p>或者不新建文件，在文件夹中，按住 Shift 右键，在此处打开 powershell，然后粘贴代码 <code>tree /f &gt; tree_output.txt</code> 即可</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616142140.png" alt="image.png"></p><p>在当前文件夹搜索栏左侧的路径下，直接敲入 CMD，回车即可</p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>Excel 操作指南</title>
    <link href="https://coffeelize.top/posts/Excel-operation-guide.html"/>
    <id>https://coffeelize.top/posts/Excel-operation-guide.html</id>
    <published>2024-06-16T02:34:53.000Z</published>
    <updated>2024-06-22T09:44:43.363Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="保留源列宽"><a href="#保留源列宽" class="headerlink" title="保留源列宽"></a>保留源列宽</h3><p>目的：复制表格时，保持表格列宽格式相同</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105530.png" alt="image.png"></p><h3 id="尽量不要合并单元格"><a href="#尽量不要合并单元格" class="headerlink" title="尽量不要合并单元格"></a>尽量不要合并单元格</h3><ul><li>通过筛选之后，合并的单元格无法进行复制</li><li>跨行合并的数据可能影响筛选的结果</li></ul><h3 id="统计数据出现的次数"><a href="#统计数据出现的次数" class="headerlink" title="统计数据出现的次数"></a>统计数据出现的次数</h3><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105519.png" alt="image.png"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=IF(A2&lt;&gt;A1, COUNTIF(A:A, A2), "")</span><br></pre></td></tr></tbody></table></figure><p>为什么第 6 行和第 7 行单元格为空呢：通过 IF 函数进行判断，上下两行内容相同，所以显示为空</p><h3 id="统计不同种类的数据"><a href="#统计不同种类的数据" class="headerlink" title="统计不同种类的数据"></a>统计不同种类的数据</h3><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616104337.png" alt="image.png"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=IF(COUNTIF($A$2:A2,A2)=1,MAX($B$1:B1)+1,"")</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">% 判断某一行的数据在整列当中是否为第一次出现</span><br><span class="line">COUNTIF($A$2:A2,A2)=1</span><br><span class="line"></span><br><span class="line">% 如果第一次出现，则值为1；之后每出现一个第一次出现的新数据，则该数据每次+1</span><br><span class="line">—&gt; MAX($B$1:B1)+1</span><br><span class="line"></span><br><span class="line">% 数据不是第一次出现，则为空值</span><br></pre></td></tr></tbody></table></figure><p>如上图所示，第 6，7，9 行都为空值，能不能让这些行都带上编号呢：</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105122.png" alt="image.png"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=IF(COUNTIF($A$2:A2,A2)=1,MAX($B$1:B1)+1,VLOOKUP(A2,$A$1:B1,2,FALSE))</span><br></pre></td></tr></tbody></table></figure><p>第 6，7，9 行之所以为空值，是因为第二行中第一次出现了该数据，因此只需查询到第一次出现数据的第二列编号即可，而 VLOOKUP 函数会自动从上往下进行查找，就能正确的找到第二列的编号。</p><h3 id="复制工作表"><a href="#复制工作表" class="headerlink" title="复制工作表"></a>复制工作表</h3><p>按住 Ctrl 键拖动即可复制工作表</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105637.png" alt="image.png"></p><h3 id="查找工作表当中的合并单元格"><a href="#查找工作表当中的合并单元格" class="headerlink" title="查找工作表当中的合并单元格"></a>查找工作表当中的合并单元格</h3><p>需求：从别人接手的工作表，很可能包含大量合并的单元格，需要将它们取消合并</p><p>1、查找，进入 <code>格式</code> 选择</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105816.png" alt="image.png"></p><p>2、勾选 <code>合并单元格</code></p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616105837.png" alt="image.png"></p><h3 id="宏绑定快捷键"><a href="#宏绑定快捷键" class="headerlink" title="宏绑定快捷键"></a>宏绑定快捷键</h3><p>如下图所示，不过不支持 Ctrl+ 数字键，那么就换成字母吧</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616110637.png" alt="image.png"></p><h3 id="单元格是否存在某些内容"><a href="#单元格是否存在某些内容" class="headerlink" title="单元格是否存在某些内容"></a>单元格是否存在某些内容</h3><p>例如，若 E 列中存在 <code>PH值</code>、<code>PH</code>、<code>PH50%</code> 这些字样，那么在 I 列中将其提取出来</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616111131.png" alt="image.png"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=IF(ISNUMBER(SEARCH("pH", E4)), E4, "")</span><br></pre></td></tr></tbody></table></figure><p>为什么要用 ISNUMBER 函数：因为 SEARCH 函数在未找到指定的字符串时会返回错误值，而不是返回 0。<br>比如没有找到相应的文字，那么 search 返回 false，isnumber 函数返回 false，最终就返回空值。如果找到了相应的文字，那么 search 返回对应的索引，isnumber 函数返回 true，最终返回</p><hr><p>进一步地，将一个词的条件变为多个词，需求如下：</p><p>只要单元格存在 <code>氢氰酸</code>、<code>总氰</code>、<code>游离氢氰酸</code>、<code>游离丙酮</code>、<code>硫酸丙酮</code>、<code>氰醇</code> 这几个词中的某一个，那么就判断正确（即需要在其他列中将其提取出），否则为空</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">=IF(</span><br><span class="line">    OR(</span><br><span class="line">        ISNUMBER(SEARCH("氢氰酸", E4)),</span><br><span class="line">        ISNUMBER(SEARCH("总氰", E4)),</span><br><span class="line">        ISNUMBER(SEARCH("游离氢氰酸", E4)),</span><br><span class="line">        ISNUMBER(SEARCH("游离丙酮", E4)),</span><br><span class="line">        ISNUMBER(SEARCH("硫酸", E4)),</span><br><span class="line">        ISNUMBER(SEARCH("丙酮氰醇含量", E4))</span><br><span class="line">    ),</span><br><span class="line">    E4,</span><br><span class="line">    ""</span><br><span class="line">)</span><br></pre></td></tr></tbody></table></figure><h3 id="最小公倍数"><a href="#最小公倍数" class="headerlink" title="最小公倍数"></a>最小公倍数</h3><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=LCM(B2:B5)</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616112110.png" alt="image.png"></p><h3 id="合并单元格-宏程序"><a href="#合并单元格-宏程序" class="headerlink" title="合并单元格 - 宏程序"></a>合并单元格 - 宏程序</h3><p>假设三个单元格都存在数据，将这连续的三个单元格合并时，默认只会保留左上角单元格的数据，其他单元格数据丢失。而如果有如下需求：需要将多个单元格数据都保留下来</p><p><img data-src="https://s2.loli.net/2024/06/21/Rh7WlzgIAvujyKB.gif"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">Sub 合并选定单元格()</span><br><span class="line">    Dim rng As Range</span><br><span class="line">    Dim mergedCell As Range</span><br><span class="line">    Dim cell As Range</span><br><span class="line">    Dim text As String</span><br><span class="line">    </span><br><span class="line">    ' 检查是否有选定的单元格</span><br><span class="line">    If Selection.Cells.Count &lt; 2 Then</span><br><span class="line">        MsgBox "请选择至少2个单元格进行合并。"</span><br><span class="line">        Exit Sub</span><br><span class="line">    End If</span><br><span class="line">    </span><br><span class="line">    Set rng = Selection ' 获取选定的单元格范围</span><br><span class="line">    </span><br><span class="line">    ' 创建一个合并单元格</span><br><span class="line">    Set mergedCell = rng.Cells(1)</span><br><span class="line">    </span><br><span class="line">    ' 将其他单元格的值添加到合并单元格中</span><br><span class="line">    For Each cell In rng</span><br><span class="line">        If cell.Value &lt;&gt; "" Then</span><br><span class="line">            text = text &amp; cell.Value &amp; Chr(10) ' Chr(10) 表示换行符</span><br><span class="line">        End If</span><br><span class="line">    Next cell</span><br><span class="line">    </span><br><span class="line">    ' 去除最后一个换行符</span><br><span class="line">    text = Left(text, Len(text) - 1)</span><br><span class="line">    </span><br><span class="line">    ' 将合并后的文本赋值给合并单元格</span><br><span class="line">    mergedCell.Value = text</span><br><span class="line">    </span><br><span class="line">    ' 合并单元格</span><br><span class="line">    rng.Merge</span><br><span class="line">End Sub</span><br></pre></td></tr></tbody></table></figure><h3 id="拆解合并的单元格（并填充内容）"><a href="#拆解合并的单元格（并填充内容）" class="headerlink" title="拆解合并的单元格（并填充内容）"></a>拆解合并的单元格（并填充内容）</h3><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240616110145.png" alt="image.png"></p><p>例如第 145 和 146 行，按照常规拆解单元格流程，拆解后只有 145 行保留数据，146 行数据为空。<br>需求如下：如何保持每一格单元格的内容和拆解前的保持一致</p><figure class="highlight vb"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Sub</span> 宏<span class="number">1</span>()</span><br><span class="line"><span class="comment">'</span></span><br><span class="line"><span class="comment">' 宏1 宏</span></span><br><span class="line"><span class="comment">' 取消合并行。请注意，这段代码假设你只选择了一个连续的单元格范围。如果选择的范围包含多个不连续的区域，代码可能无法正常工作。确保选择的范围是连续的单元格范围。</span></span><br><span class="line"><span class="comment">'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">'</span></span><br><span class="line">    <span class="keyword">Dim</span> selectedRange <span class="keyword">As</span> Range</span><br><span class="line">    <span class="keyword">Set</span> selectedRange = Selection <span class="comment">' 将选择的单元格范围存储到变量中</span></span><br><span class="line">    </span><br><span class="line">    selectedRange.<span class="keyword">Select</span></span><br><span class="line">    Selection.UnMerge</span><br><span class="line">    selectedRange.Rows(<span class="number">1</span>).AutoFill Destination:=selectedRange, Type:=xlFillCopy <span class="comment">' 使用第一行的内容自动填充整个范围</span></span><br><span class="line">    selectedRange.<span class="keyword">Select</span></span><br><span class="line">    selectedRange.Cells(selectedRange.Rows.Count, selectedRange.Columns.Count).<span class="keyword">Select</span> <span class="comment">' 选中范围中的最后一个单元格</span></span><br><span class="line"><span class="keyword">End</span> <span class="keyword">Sub</span></span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://s2.loli.net/2024/06/16/AEsXvW4lTRC6qnF.gif"></p><h3 id="计算单元格中字符出现的次数"><a href="#计算单元格中字符出现的次数" class="headerlink" title="计算单元格中字符出现的次数"></a>计算单元格中字符出现的次数</h3><p><img data-src="https://s2.loli.net/2024/06/21/5Qpiew3kAJST6R9.png" alt="image.png"></p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">=LEN(A2) - LEN(SUBSTITUTE(A2, "k", ""))</span><br></pre></td></tr></tbody></table></figure><p>公式思路：先计算单元格中总的字符长度，然后将要找到字符替换为空字符，那么『总长度』减去『替换为空字符后的长度』，就是你要找到字符的个数<br>SUBSTITUTE：将 <code>"k"</code> 替换为空字符 <code>""</code></p><h3 id="ROUNDUP-函数"><a href="#ROUNDUP-函数" class="headerlink" title="ROUNDUP 函数"></a>ROUNDUP 函数</h3><p>参考资料：<a href="https://support.microsoft.com/zh-cn/office/roundup-%E5%87%BD%E6%95%B0-f8bc9b23-e795-47db-8703-db171d0c42a7">Fetching Title#mrdb</a></p><p>朝着远离 0（零）的方向将数字进行向上舍入：</p><ul><li>ROUNDUP 的行为与 ROUND 相似，所不同的是它始终将数字进行向上舍入</li><li>如果 num_digits 大于 0（零），则将数字向上舍入到指定的小数位数。</li><li>如果 num_digits 为 0，则将数字向上舍入到最接近的整数。</li><li>如果 num_digits 小于 0，则将数字向上舍入到小数点左边的相应位数。</li></ul><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">=ROUNDUP(3.001,0) —&gt; 4</span><br><span class="line">=ROUNDUP(3.01,1) —&gt; 3.1</span><br><span class="line"></span><br><span class="line">注意：该函数并不考虑什么四舍五入，都是向上取整</span><br><span class="line"></span><br><span class="line">=ROUNDUP(-3.14159, 1) —&gt; 如果第一个参数是正数，那么返回值是3.2；是负数，返回-3.2</span><br><span class="line"></span><br><span class="line">=ROUNDUP(31415.92654, -2) —&gt; 将 31415.92654 向上舍入到小数点左边两位数，结果为31500</span><br></pre></td></tr></tbody></table></figure><h3 id="多列数据合并（自动添加分隔符）"><a href="#多列数据合并（自动添加分隔符）" class="headerlink" title="多列数据合并（自动添加分隔符）"></a>多列数据合并（自动添加分隔符）</h3><p>未完待续…</p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="Office" scheme="https://coffeelize.top/tags/Office/"/>
    
  </entry>
  
  <entry>
    <title>Word 操作指南</title>
    <link href="https://coffeelize.top/posts/Word-operation-guide.html"/>
    <id>https://coffeelize.top/posts/Word-operation-guide.html</id>
    <published>2024-06-14T07:19:53.000Z</published>
    <updated>2024-06-22T10:01:46.510Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="粘贴时保留纯文本"><a href="#粘贴时保留纯文本" class="headerlink" title="粘贴时保留纯文本"></a>粘贴时保留纯文本</h3><p>参考资料：<a href="https://jingyan.baidu.com/article/215817f78099da5fda1423da.html#:~:text=%E6%96%B9%E6%B3%95%2F%E6%AD%A5%E9%AA%A4&amp;text=%E6%89%93%E5%BC%80WORD%E6%96%87%E6%A1%A3%EF%BC%8C%E7%82%B9%E5%87%BB%E6%96%87%E4%BB%B6,%E9%80%89%E9%A1%B9%EF%BC%8C%E5%BC%B9%E5%87%BA%E9%80%89%E9%A1%B9%E8%AE%BE%E7%BD%AE%E6%A1%86%E3%80%82&amp;text=%E7%82%B9%E5%87%BB%E2%80%9C%E9%AB%98%E7%BA%A7%E2%80%9D%E9%80%89%E9%A1%B9%E5%8D%A1%EF%BC%8C,%E4%BB%85%E4%BF%9D%E7%95%99%E6%96%87%E6%9C%AC%E2%80%9D%E5%8D%B3%E5%8F%AF%E3%80%82">如何设置 WORD 粘贴时默认仅保留文本格式 - 百度经验</a></p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614152058.png" alt="image.png"></p><p>之后从浏览器中粘贴过来，就不需要在按一次 Ctrl，然后再按 T 了，直接粘贴为纯文本格式</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614152107.png" alt="image.png"></p><h3 id="使用自定义模板"><a href="#使用自定义模板" class="headerlink" title="使用自定义模板"></a>使用自定义模板</h3><p>参考资料：<a href="https://blog.csdn.net/glgom/article/details/115940158">office 增加自定义文档模板_用户可自定义文档类型的模板，对文档模板进行规范，并可定义模板中的 “签字标记”-CSDN 博客</a></p><ol><li>打开手头的 word 模板</li><li>另存为 dotx，会自动跳转到自定义 office 模板的文件夹路径，保存</li><li>再次新建 word 文档的时候，可从 <code>个人</code> 的模板中选择进行新建文档</li></ol><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614152435.png" alt="image.png"></p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614152439.png" alt="image.png"></p><h3 id="Mathtype-插入公式"><a href="#Mathtype-插入公式" class="headerlink" title="Mathtype 插入公式"></a>Mathtype 插入公式</h3><p>如果使用中文输入法，那么输出的 x 这样的字符就不是标准的数学字体，切换成英文</p><p><img data-src="https://s2.loli.net/2024/06/14/akbZ73Hzg9h45uG.gif"></p><h3 id="Word-自带的公式"><a href="#Word-自带的公式" class="headerlink" title="Word 自带的公式"></a>Word 自带的公式</h3><p>有专用和线性区别，比如说如下的 Cambria Math 字体，还有两种显示模式</p><p><img data-src="https://s2.loli.net/2024/06/14/abAZgeXv1yFHpqL.gif"></p><h3 id="调整表格行高"><a href="#调整表格行高" class="headerlink" title="调整表格行高"></a>调整表格行高</h3><p>问题：直接调整段落，设置为最小值，表格之间仍然还是有间隙</p><p>1、先手动减小这个高度</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614153137.png" alt="image.png"></p><p>2、调整完之后，行与行之间的间隙没有了</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614153155.png" alt="image.png"></p><p>3、此时在调整为最小值</p><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240614153210.png" alt="image.png"></p><h3 id="网页文字复制"><a href="#网页文字复制" class="headerlink" title="网页文字复制"></a>网页文字复制</h3><p>有些网站是禁止复制文字的 —&gt; 在不使用浏览器插件的情况下，可以将网页保存为 mhtml 本地文件</p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="Office" scheme="https://coffeelize.top/tags/Office/"/>
    
  </entry>
  
  <entry>
    <title>Mermaid 甘特图</title>
    <link href="https://coffeelize.top/posts/Mermaid-Gantt-chart.html"/>
    <id>https://coffeelize.top/posts/Mermaid-Gantt-chart.html</id>
    <published>2024-06-12T13:15:50.000Z</published>
    <updated>2024-06-22T09:53:42.242Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h3 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h3><ul><li>mermaid 中文网教程：<a href="https://mermaid.nodejs.cn/syntax/gantt.html">甘特图 | Mermaid 中文网</a></li><li> mermaid 在线编辑器：<a href="https://mermaid.live/edit">Online FlowChart &amp; Diagrams Editor - Mermaid Live Editor</a></li></ul><h3 id="案例"><a href="#案例" class="headerlink" title="案例"></a>案例</h3><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">gantt</span><br><span class="line">  title 项目进度</span><br><span class="line">  dateFormat YYYY-MM-DD</span><br><span class="line">  section 设计</span><br><span class="line">  任务1: a1, 2022-01-01, 3d</span><br><span class="line">  任务2: a2, after a1, 2d</span><br><span class="line">  %% 注释内容</span><br><span class="line">  section 开发</span><br><span class="line">  任务3: b1, after a2, 4d</span><br><span class="line">  里程碑: milestone, after b1</span><br><span class="line">  section 测试</span><br><span class="line">  任务4:c1, after b1, 2d</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240612212555.png"></p><h4 id="修改坐标轴格式"><a href="#修改坐标轴格式" class="headerlink" title="修改坐标轴格式"></a>修改坐标轴格式</h4><p>坐标轴（横坐标）默认输出日期格式为 YYYY-MM-DD，以天作为单位，如何以分钟或者秒作为横坐标的单位呢：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">axisFormat %Y-%m-%d</span><br></pre></td></tr></tbody></table></figure><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">%a - 缩写的星期几名称。</span><br><span class="line">%A - 完整的星期几名称。</span><br><span class="line">%b - 缩写的月份名称。</span><br><span class="line">%B - 完整的月份名称。</span><br><span class="line">%c - 日期和时间，格式为 "%a %b %e %H:%M:%S %Y"。</span><br><span class="line">%d - 以十进制数表示的零填充的月份中的日期 [01,31]。</span><br><span class="line">%e - 以十进制数表示的空格填充的月份中的日期 [ 1,31]；等同于 %_d。</span><br><span class="line">%H - 小时（24小时制）的十进制数表示 [00,23]。</span><br><span class="line">%I - 小时（12小时制）的十进制数表示 [01,12]。</span><br><span class="line">%j - 以十进制数表示的一年中的日期 [001,366]。</span><br><span class="line">%m - 以十进制数表示的月份 [01,12]。</span><br><span class="line">%M - 以十进制数表示的分钟 [00,59]。</span><br><span class="line">%L - 以十进制数表示的毫秒数 [000, 999]。</span><br><span class="line">%p - 上午（AM）或下午（PM）。</span><br><span class="line">%S - 以十进制数表示的秒数 [00,61]。</span><br><span class="line">%U - 以十进制数表示的一年中的周数（以星期日作为一周的第一天） [00,53]。</span><br><span class="line">%w - 以十进制数表示的星期几 [0（星期日）,6]。</span><br><span class="line">%W - 以十进制数表示的一年中的周数（以星期一作为一周的第一天） [00,53]。</span><br><span class="line">%x - 日期，格式为 "%m/%d/%Y"。</span><br><span class="line">%X - 时间，格式为 "%H:%M:%S"。</span><br><span class="line">%y - 以十进制数表示的不带世纪的年份 [00,99]。</span><br><span class="line">%Y - 以十进制数表示的带世纪的年份。</span><br><span class="line">%Z - 时区偏移，例如 "-0700"。</span><br><span class="line">%% - 字面上的 "%" 字符。</span><br></pre></td></tr></tbody></table></figure><p>例如需要将坐标轴改为小时和分钟，那么：</p><figure class="highlight diff"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">gantt</span><br><span class="line">    title 甘特图</span><br><span class="line"><span class="addition">+   axisFormat %H-%M</span></span><br><span class="line"><span class="addition">+   dateFormat  HH:mm</span></span><br><span class="line">    section 样本1</span><br><span class="line">    任务1:a1,00:00, 70s</span><br><span class="line">    任务2:after a1, 100s</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240612213529.png" alt="image.png"></p><p>将坐标轴改成分钟和秒，那么：</p><figure class="highlight diff"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">gantt</span><br><span class="line">    title 效率计算</span><br><span class="line"><span class="addition">+   axisFormat %M:%S</span></span><br><span class="line"><span class="addition">+   dateFormat  mm:ss</span></span><br><span class="line">%% 进样</span><br><span class="line">    section 流程1</span><br><span class="line">    步骤1: milestone,a0,0,0s</span><br><span class="line">    步骤2: a1,after a0,8.6s</span><br><span class="line">    步骤3: a2,after a1,3s</span><br><span class="line">    步骤4: a3,after a2,10s</span><br><span class="line">    section 流程2</span><br><span class="line">    步骤2: b1,after a2,8.6s</span><br><span class="line">    步骤3: b2,after b1,3s</span><br><span class="line">    步骤4: b3,after b2,10s</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240612213950.png" alt="image.png"></p><h4 id="给里程碑取别名"><a href="#给里程碑取别名" class="headerlink" title="给里程碑取别名"></a>给里程碑取别名</h4><figure class="highlight diff"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">gantt</span><br><span class="line">    dateFormat HH:mm</span><br><span class="line">    axisFormat %H:%M</span><br><span class="line"><span class="addition">+   Initial milestone : milestone, m1, 17:49, 2m</span></span><br><span class="line">    Task A : 10m</span><br><span class="line">    Task B : 5m</span><br><span class="line"><span class="addition">+   Final milestone : milestone, m2, 18:08, 4m</span></span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240612214239.png" alt="image.png"></p><h3 id="某效率计算"><a href="#某效率计算" class="headerlink" title="某效率计算"></a>某效率计算</h3><p>案例分析如下，对于有同步运行的动作，可通过这种时间重叠的方式，求出仪器检测样本的最快时间：</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">gantt</span><br><span class="line">    title 水分检测效率计算</span><br><span class="line">    axisFormat %M-%S</span><br><span class="line">    dateFormat  mm-ss</span><br><span class="line">   </span><br><span class="line">    section 样本1</span><br><span class="line">    开始检测: milestone,SF1-0,0,0s</span><br><span class="line">    样本瓶就位:SF1-1,after SF1-0,10s</span><br><span class="line">    夹取注射器: SF1-2,after SF1-0,10s</span><br><span class="line">    开盖:SF1-3,after SF1-1,10s</span><br><span class="line">    润洗3次注射器: SF1-4,after SF1-2,45s</span><br><span class="line">    抽取样品: SF1-5,after SF1-4,10s</span><br><span class="line">    拧盖:SF1-6,after SF1-5,10s</span><br><span class="line">    称重: SF1-7,after SF1-5,20s</span><br><span class="line">    注入仪器:SF1-8,after SF1-7,20s</span><br><span class="line">    称重: SF1-9,after SF1-8,20s</span><br><span class="line">    注射器放托盘: SF1-10,after SF1-9,10s</span><br><span class="line">    水分检测:SF1-11,after SF1-8,240s</span><br><span class="line"></span><br><span class="line">    section 样本2</span><br><span class="line">    样本瓶就位:SF2-1,after SF1-10,10s</span><br><span class="line">    夹取注射器: SF2-2,after SF1-10,10s</span><br><span class="line">    开盖:SF2-3,after SF2-1,10s</span><br><span class="line">    润洗3次注射器: SF2-4,after SF2-2,45s</span><br><span class="line">    抽取样品: SF2-5,after SF2-4,10s</span><br><span class="line">    拧盖:SF2-6,after SF2-5,10s</span><br><span class="line">    称重: SF2-7,after SF2-5,20s</span><br><span class="line">    注入仪器:SF2-8,after SF2-7,20s</span><br><span class="line">    称重: SF2-9,after SF2-8,20s</span><br><span class="line">    注射器放托盘: SF2-10,after SF2-9,10s</span><br><span class="line">    水分检测:SF2-11,after SF2-8,240s</span><br><span class="line"></span><br><span class="line">    section 样本3</span><br><span class="line">    样本瓶就位:SF3-1,after SF2-10,10s</span><br><span class="line">    夹取注射器: SF3-2,after SF2-10,10s</span><br><span class="line">    开盖:SF3-3,after SF3-1,10s</span><br><span class="line">    润洗3次注射器: SF3-4,after SF3-2,45s</span><br><span class="line">    抽取样品: SF3-5,after SF3-4,10s</span><br><span class="line">    拧盖:SF3-6,after SF3-5,10s</span><br><span class="line">    称重: SF3-7,after SF3-5,20s</span><br><span class="line">    注入仪器:SF3-8,after SF3-7,20s</span><br><span class="line">    称重: SF3-9,after SF3-8,20s</span><br><span class="line">    注射器放托盘: SF3-10,after SF3-9,10s</span><br><span class="line">    水分检测:SF3-11,after SF3-8,240s</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://coffeelize-1307708315.cos.ap-beijing.myqcloud.com/imgs/blog20240612214658.png" alt="image.png"></p><p>Tips：每个样本检测需要执行的操作都是一样的。第一个样本的代码写完后，后续可以通过查找替换的方式，进行批量替换。例如在样本一中将 <code>SF1-1</code> 第一个 <code>1</code> 替换为 <code>2</code>，即 <code>SF2-1</code>，样本 2 的代码便很快可以修改完毕。</p>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="image" scheme="https://coffeelize.top/tags/image/"/>
    
    <category term="mermaid" scheme="https://coffeelize.top/tags/mermaid/"/>
    
  </entry>
  
  <entry>
    <title>QHUMaster 使用指南</title>
    <link href="https://coffeelize.top/posts/QHUMaster-User&#39;s-Guide.html"/>
    <id>https://coffeelize.top/posts/QHUMaster-User&#39;s-Guide.html</id>
    <published>2024-01-09T13:25:10.000Z</published>
    <updated>2024-06-22T09:57:50.722Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="资料准备"><a href="#资料准备" class="headerlink" title="资料准备"></a>资料准备</h2><table><thead><tr><th>文件名</th><th>下载</th></tr></thead><tbody><tr><td> QHUMaster.zip</td><td><a href="https://github.com/coffeelize/coffeelize.github.io/blob/master/download/QHUMaster.zip">QHUMaster.zip</a></td></tr><tr><td> 一份简短的 LaTeX 介绍.pdf </td><td><a href="https://github.com/coffeelize/coffeelize.github.io/blob/master/download/%E4%B8%80%E4%BB%BD%E7%AE%80%E7%9F%AD%E7%9A%84LaTeX%E4%BB%8B%E7%BB%8D.pdf">一份简短的 LaTeX 介绍.pdf</a></td></tr></tbody></table><h2 id="Overleaf-在线编译"><a href="#Overleaf-在线编译" class="headerlink" title="Overleaf 在线编译"></a>Overleaf 在线编译</h2><h3 id="注册-or-登录帐号"><a href="#注册-or-登录帐号" class="headerlink" title="注册 or 登录帐号"></a>注册 or 登录帐号</h3><p>官网：<a href="https://www.overleaf.com/project">Online LaTeX Editor</a></p><h3 id="新建项目"><a href="#新建项目" class="headerlink" title="新建项目"></a>新建项目</h3><p>Projects —&gt; Create a new project —&gt; Blank project (空项目) —&gt; 为项目取一个名字</p><p><img data-src="https://s2.loli.net/2024/01/09/kabndM4ozVc9KWZ.png" alt="image.png"></p><p>创建项目完之后，将出现如下界面：</p><p><img data-src="https://s2.loli.net/2024/01/09/oqa5lxQL7dhREj9.png" alt="image.png"></p><h3 id="导入项目"><a href="#导入项目" class="headerlink" title="导入项目"></a>导入项目</h3><p>1）对 QHUMaster.zip 进行解压，得如下文件；</p><p><img data-src="https://s2.loli.net/2024/01/09/gQRtCHrUbfwe3Nu.png" alt="image.png"></p><p>2）将 Manuscript.tex、QHUMaster.cls 以及 reference.bib 拖入到 Overleaf 的项目当中，进行上传</p><p><img data-src="https://s2.loli.net/2024/01/09/8PQrEUW57tKpV1A.png" alt="image.png"></p><p>3）新建文件夹，取名 <code>imgs</code></p><p><img data-src="https://s2.loli.net/2024/01/09/nODSKBrG46jUeXN.png" alt="image.png"></p><p>将 imgs 文件夹中的两张图片拖入 overleaf 项目中的 imgs 文件夹下，进行上传<br><img data-src="https://s2.loli.net/2024/01/09/xMt36FSDCOH8YWh.png" alt="image.png"></p><h3 id="项目设置"><a href="#项目设置" class="headerlink" title="项目设置"></a>项目设置</h3><p>1）全选复制 <code>Manuscript.tex</code> 中的所有内容；<br>``<br><img data-src="https://s2.loli.net/2024/01/09/D15TYJVenckNZRr.png" alt="image.png"></p><p>2）删除 <code>main.tex</code> 文件中的所有内容，粘贴刚才复制的内容到 <code>main.tex</code> </p><p>3）点击左上角的 Menu，将 pdfLaTeX 改为 XeLaTeX</p><p><img data-src="https://s2.loli.net/2024/01/09/osG98VcPhnmw3La.png" alt="image.png"></p><h3 id="编译文件"><a href="#编译文件" class="headerlink" title="编译文件"></a>编译文件</h3><p>接下来按快捷键 <code>Ctrl+S</code>，项目开始编译；编译结束后右侧将出现生成的 PDF 文件</p><p><img data-src="https://s2.loli.net/2024/01/09/odFphf2OgEJA4vD.png" alt="image.png"></p><h3 id="相关操作"><a href="#相关操作" class="headerlink" title="相关操作"></a>相关操作</h3><ul><li>下载 PDF 文件</li></ul><p><img data-src="https://s2.loli.net/2024/01/09/qTbPaefZjXYF1GB.png" alt="image.png"></p><ul><li>打包下载整个项目</li></ul><p><img data-src="https://s2.loli.net/2024/01/09/VxlIn2aijCeuyoU.png" alt="image.png"></p><ul><li>多人共同编辑：Share —&gt; 通过邮件分享项目，可多人在线同时编辑</li></ul><p><img data-src="https://s2.loli.net/2024/01/09/cJwXrpYxhm2tKyd.png" alt="image.png"></p><ul><li>代码和 PDF 位置的跳转</li></ul><p><img data-src="https://s2.loli.net/2024/01/09/moaTYqizg3xQdOp.png" alt="image.png"></p><h2 id="模板介绍"><a href="#模板介绍" class="headerlink" title="模板介绍"></a>模板介绍</h2><h3 id="中英文封面修改"><a href="#中英文封面修改" class="headerlink" title="中英文封面修改"></a>中英文封面修改</h3><p><img data-src="https://s2.loli.net/2024/01/09/5X8otNPwusj1l2c.png" alt="image.png"></p><p>同理，可以相应修改英文封面的内容</p><p><img data-src="https://s2.loli.net/2024/01/09/mrZFnJI7dgxS6pc.png" alt="image.png"></p><h3 id="命令介绍"><a href="#命令介绍" class="headerlink" title="命令介绍"></a>命令介绍</h3><p>这里仅对照图片介绍部分命令，对于 LaTeX 通用命令，大家完全可以使用 GPT 或者搜索引擎就行搜索</p><figure class="highlight plaintext"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">% 插入章节</span><br><span class="line">\chapter{时运不齐，命途多舛}</span><br><span class="line">% 插入小节</span><br><span class="line">\section{插入图片}</span><br><span class="line">% 插入假文</span><br><span class="line">\zhlipsum[1]</span><br></pre></td></tr></tbody></table></figure><p><img data-src="https://s2.loli.net/2024/01/09/MvEmwVUp8Ku9jYP.png" alt="image.png"></p><h2 id="LaTeX-实用资源"><a href="#LaTeX-实用资源" class="headerlink" title="LaTeX 实用资源"></a>LaTeX 实用资源</h2><ul><li>LaTeX 工作室：<a href="https://www.latexstudio.net/">LaTeX 工作室</a><ul><li><a href="https://www.latexstudio.net/texdoc/#/29?page_id=155">入门看哪些文档 - LaTeX 工作室</a></li><li><a href="https://ask.latexstudio.net/ask/">首页 - LaTeX 工作室 问答社区</a></li></ul></li><li> CTAN.org 宏包大全：<a href="https://ctan.org/pkg/">CTAN: Packages</a></li><li>CTEX.org 常用宏包：<a href="http://www.ctex.org/documents/packages/">CTEX - 在线文档 - TeX/LaTeX 常用宏包</a></li><li> CTEX.org：<a href="http://www.ctex.org/documents/latex/graphics/graphics.html">LATEX2e&nbsp;插图指南</a></li><li> CTEX.org 主页：<a href="http://www.ctex.org/HomePage#">科技排版系统</a></li><li> LaTeX 编辑部：<a href="https://www.latexstudio.net/hulatex/index.htm">LaTeX 编辑部</a></li><li><a href="https://coffeelize.top/posts/a9e583b4.html">LaTeX 相关资源汇总 | 智朋的个人博客</a></li></ul>]]></content>
    
    
      
      
    <summary type="html"></summary>
      
    
    
    
    
    <category term="Latex" scheme="https://coffeelize.top/tags/Latex/"/>
    
  </entry>
  
</feed>
